它与Spring兼容的原因是测试类由Spring容器通过使用进行管理
@RunWith(SpringJUnit4ClassRunner.class)。运行程序会将所有托管对象注入测试对象。
JerseyTest不以这种方式进行管理。
如果需要,您可以创建自己的运行程序,但是您需要稍微了解一下HK2(Jersey的DI框架)的工作方式。看一下文档。一切都围绕着
ServiceLocator。在独立环境中,您可能会看到类似的内容来引导DI容器
ServiceLocatorFactory factory = ServiceLocatorFactory.getInstance();ServiceLocator locator = factory.create(null);ServiceLocatorUtilities.bind(locator, new MyBinder());
然后获得服务,做
Service service = locator.getService(Service.class);
在测试类的情况下,我们不需要获得对服务对象的任何访问权限,我们可以简单地使用注入测试对象
ServiceLocator:
locator.inject(test);
上面
test是在自定义运行器中传递给我们的测试类实例。这是自定义运行器的示例实现
import java.lang.annotation.*;import org.glassfish.hk2.api.*;import org.glassfish.hk2.utilities.*;import org.junit.runners.BlockJUnit4ClassRunner;import org.junit.runners.model.*;public class Hk2ClassRunner extends BlockJUnit4ClassRunner { private final ServiceLocatorFactory factory = ServiceLocatorFactory.getInstance(); private Class<? extends Binder>[] binderClasses; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public static @interface Binders { public Class<? extends Binder>[] value(); } public Hk2ClassRunner(Class<?> cls) throws InitializationError { super(cls); Binders bindersAnno = cls.getClass().getAnnotation(Binders.class); if (bindersAnno == null) { binderClasses = new Class[0]; } } @Override public Statement methodInvoker(frameworkMethod method, final Object test) { final Statement statement = super.methodInvoker(method, test); return new Statement() { @Override public void evaluate() throws Throwable { ServiceLocator locator = factory.create(null); for (Class<? extends Binder> c : binderClasses) { try { ServiceLocatorUtilities.bind(locator, c.newInstance()); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } } locator.inject(test); statement.evaluate(); locator.shutdown(); } }; }}在运行程序中,
methodInvoker每个测试方法都会调用,因此我们正在为每个调用的测试方法创建一组新的对象。
这是一个完整的测试案例
@Binders({ServiceBinder.class})@RunWith(Hk2ClassRunner.class)public class InjectTest { public static class Service { @Inject private Demo demo; public void doSomething() { System.out.println("Inside Service.doSomething()"); demo.doSomething(); } } public static class Demo { public void doSomething() { System.out.println("Inside Demo.doSomething()"); } } public static class ServiceBinder extends AbstractBinder { @Override protected void configure() { bind(Demo.class).to(Demo.class); bind(Service.class).to(Service.class); } } @Inject private Service service; @Test public void testInjections() { Assert.assertNotNull(service); service.doSomething(); }}


