كيفية وحدة اختبار جيرسي + غويس:سيرفيسيلوكاتور?
-
21-12-2019 - |
سؤال
باستخدام هونج كونج 2 guice-bridge
تمكنت من دمج جيرسي 2.س مع غويس 3.x.
public class MyApp extends ResourceConfig {
@Inject
public MyApp(ServiceLocator serviceLocator) {
packages("com.mycompany");
...
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(GuiceContext.INJECTOR);
}
}
لكن الآن لم تعد اختبارات القميص الخاصة بي تعمل.
public abstract class AbstractJerseyTest extends JerseyTest {
public AbstractJerseyTest() throws TestContainerException {
super(new InMemoryTestContainerFactory());
}
protected Application configure() {
new MyApp(); // ERROR: missing 'ServiceLocator'
}
}
إذن من أين أحصل على ServiceLocator
لاختبارات وحدتي?
المحلول 4
التي قطعناها على أنفسنا من العمل مع مساعدة من رائع:
public class MemoryTestContainerFactory implements TestContainerFactory {
private final Class<? extends Application> jaxrsApplicationClass;
public MemoryTestContainerFactory(Class<? extends Application> jaxrsApplicationClass) {
this.jaxrsApplicationClass = jaxrsApplicationClass;
}
@Override
public TestContainer create(URI baseUri, DeploymentContext context) throws IllegalArgumentException {
return new MemoryTestContainer(jaxrsApplicationClass, baseUri, context);
}
private static class MemoryTestContainer implements TestContainer {
private final URI baseUri;
private final ApplicationHandler appHandler;
private final AtomicBoolean started = new AtomicBoolean(false);
private static final Logger LOGGER = Logger.getLogger(MemoryTestContainer.class.getName());
MemoryTestContainer(Class<? extends Application> jaxrsApplicationClass, URI baseUri, DeploymentContext context) {
this.baseUri = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();
this.appHandler = new ApplicationHandler(jaxrsApplicationClass);
}
@Override
public ClientConfig getClientConfig() {
def provider = new InMemoryConnector.Provider(baseUri, appHandler) // private access (only works with Groovy)
return new ClientConfig().connectorProvider(provider);
}
@Override
public URI getBaseUri() {
return baseUri;
}
@Override
public void start() {
if (started.compareAndSet(false, true)) {
LOGGER.log(Level.FINE, "Starting InMemoryContainer...");
} else {
LOGGER.log(Level.WARNING, "Ignoring start request - InMemoryTestContainer is already started.");
}
}
@Override
public void stop() {
if (started.compareAndSet(true, false)) {
LOGGER.log(Level.FINE, "Stopping InMemoryContainer...");
} else {
LOGGER.log(Level.WARNING, "Ignoring stop request - InMemoryTestContainer is already stopped.");
}
}
}
}
إنها ليست جميلة ، لكنها تعمل.
نصائح أخرى
ربما نهج أنظف هو ببساطة استخدام Feature
وتكوين الجسر هناك بدلا من في ResourceConfig
public class GuiceFeature implements Feature {
public void configure(FeatureContext context) {
ServiceLocator serviceLocator = ServiceLocatorProvider.getServiceLocator(context);
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(GuiceContext.INJECTOR);
}
}
يمكن تسجيل هذا مثل أي ميزة أخرى.فقط register
ذلك أو مسح لذلك مع @Provider
.
لاحظ ال ServiceLocatorProvider
متاح فقط جيرسي 2.6 وما فوق.
هنا هو الحل الذي نجح.
المفتاح هو تجاوز طريقة كونكريديبولوتيون () من جيرسيتيست وإنشاء ديبلويمنتكونتيكست عن طريق تمرير ريسورسيكونفيغ تطبيق معين.فئة بدلا من تجاوز طريقة تكوين() والعودة ريسورسيكونفيغ المثال ، بحيث حاوية الاختبار تهيئة جسر غويس بشكل صحيح.
هذا هو مع الإصدارات التالية من جيرسي ، غويس ، و هك 2 غويس جسر
<jersey.version>2.15</jersey.version>
<jackson2.version>2.4.4</jackson2.version>
<hk2.guice.bridge.version>2.4.0-b10</hk2.guice.bridge.version>
<guice.version>4.0-beta5</guice.version>
1) فئة الخدمة الخاصة بي
public interface MyService {
public void hello();
}
2) بلدي خدمة وهمية إمبل
public class MyMockServiceImpl implements MyService{
public void hello() {
System.out.println("Hi");
}
}
3) فئة الموارد الخاصة بي مع خدمة حقن غويس
@Path("myapp")
public class MyResource {
private final MyService myService;
@Inject
public MyResource(MyService myService) {
this.myService = myService;
}
}
4) فئة اختبار الموارد الخاصة بي
public class MyResourceTest extends JerseyTestNg.ContainerPerClassTest {
@Override
protected Application configure() {
return null;
}
@Override
protected DeploymentContext configureDeployment() {
return DeploymentContext.builder(MyTestConfig.class).build();
}
// other test and setup/teardown methods
}
5) فئة ريسورسيكونفيغ
static class MyTestConfig extends ResourceConfig {
@Inject
public MyTestConfig(ServiceLocator serviceLocator) {
packages("com.myapp.rest");
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(Guice.createInjector(new MyTestModule()));
}
}
6) فئة وحدة اختبار جويس الخاصة بي
public class MyTestModule implements Module {
@Override
public void configure(Binder binder) {
binder.bind(MyService.class)
.to(MyMockServiceImpl.class);
}
}
ملاحظة:لم أستخدم جيرسي من قبل.ومع ذلك ، يجب ألا تتصل new MyApp()
بعد الآن;وإلا لن يعمل غويس.بدلا من ذلك ، قد أحاول شيئا من هذا القبيل:
public abstract class AbstractJerseyTest extends JerseyTest {
private final Module[] modules;
public AbstractJerseyTest(Module... modules) throws TestContainerException {
super(new InMemoryTestContainerFactory());
this.module = modules;
}
protected Application configure() {
Injector inj = Guice.createInjector(modules);
return inj.getInstance(MyApp.class);
}
}
public class ActualTest extends AbstractJerseyTest {
private static class TestModule extends AbstractModule {
@Override
public void configure() {
// Do your guice bindings here
}
}
public ActualTest() throws TestContainerException {
super(new TestModule());
}
}