Тест JUnit с инжекцией GIN, без GWTTestCase и перегрузки модулей джина?
Я разработал новый проект, используя Guice /Gin, чтобы я мог сделать наш код более модульным и способным к обмену, особенно при тестировании.
Однако я не могу выяснить, как заставить это работать на практике. У меня сложилось впечатление, что я могу просто создать новый модуль Gin /Guice в моем тесте и установить свой "базовый" модуль, перегружая любые привязки, которые я хочу заменить конкретными реализациями тестирования.
Я не хочу использовать GWTTestCase и загружать весь мой модуль, потому что он очень медленный и не требующий упрощения для тех типов гранулярного тестирования, которые мне нужны.
Я пытался использовать Jukito ( http://code.google.com/p/jukito/), gwt-test-utils ( http://code.google.com/p/gwt-test-utils/wiki/HowToUseWithGIN) а также некоторые ресурсы о том, как сделать это с помощью хитрости ( http://fabiostrozzi.eu/2011/03/27/junit-tests-easy-guice/).
Ни один из этих методов не дает никаких результатов.
Я думаю, что подход Guice мог бы работать, если бы я определил зеркальный модуль guice для моего модуля Gin. Однако я действительно не хочу управлять обоими из них. Я действительно просто хочу протестировать мой модуль GIN, как будто я предполагаю, что люди тестируют с Guice.
Я чувствую, что это должно быть действительно просто, может кто-нибудь указать мне примеры, которые работают?
Обновить
Другой способ взглянуть на этот вопрос:
Как заставить примеры на сайте Jukito ( http://code.google.com/p/jukito/) работать, когда вводимые мной классы находятся во внешнем модуле Gin?
** Обновление - в связи с ответом Томаса Бойера **
Спасибо за подсказку, Том, мне не удалось найти примеры использования адаптера, но я все равно попытался увеличить примеры Jukito для использования GinModuleAdapter:
@RunWith(JukitoRunner.class)
public class MyGinTest {
public static class Module extends JukitoModule {
protected void configureTest() {
install(new GinModuleAdapter(new ClientModule()));
}
}
@Test
@Inject
public void testAdd(SyncedDOMModel mod){
assertNotNull(mod);
}
}
Когда я попытался запустить этот тест, я получил это исключение:
java.lang.AssertionError: should never be actually called
at com.google.gwt.inject.rebind.adapter.GwtDotCreateProvider.get(GwtDotCreateProvider.java:43)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
at com.google.inject.Scopes$1$1.get(Scopes.java:65)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
at com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:204)
at com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:198)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1024)
at com.google.inject.internal.InternalInjectorCreator.loadEagerSingletons(InternalInjectorCreator.java:198)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:179)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:109)
at com.google.inject.Guice.createInjector(Guice.java:95)
at com.google.inject.Guice.createInjector(Guice.java:72)
at com.google.inject.Guice.createInjector(Guice.java:62)
at org.jukito.JukitoRunner.ensureInjector(JukitoRunner.java:118)
at org.jukito.JukitoRunner.computeTestMethods(JukitoRunner.java:177)
at org.jukito.JukitoRunner.validateInstanceMethods(JukitoRunner.java:276)
at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:102)
at org.junit.runners.ParentRunner.validate(ParentRunner.java:344)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:74)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:55)
at org.jukito.JukitoRunner.<init>(JukitoRunner.java:72)
Мой модуль gin является частью проекта GWTP и выглядит так:
public class ClientModule extends AbstractPresenterModule {
@Override
protected void configure() {
install(new DefaultModule(ClientPlaceManager.class));
bindPresenter(MainPagePresenter.class, MainPagePresenter.MyView.class,
MainPageView.class, MainPagePresenter.MyProxy.class);
bindConstant().annotatedWith(DefaultPlace.class).to(NameTokens.main);
bindPresenterWidget(MapTreePresenter.class,
MapTreePresenter.MyView.class, MapTreeView.class);
bindPresenterWidget(MapTreeItemPresenter.class,
MapTreeItemPresenter.MyView.class, MapTreeItemView.class);
bind(ResourcePool.class).to(DefferredResourcePool.class);
bind(WebSocket.class).to(WebSocketImpl.class);
}
}
Как вы можете видеть, класс, который я добавляю в моем тесте SyncedDOMModel
, использует WebSocket
который я связываю в моем модуле. Когда я тестирую, я не хочу использовать настоящий веб-сокет и сервер. Поэтому я хочу перегрузить эту привязку в моем тесте классом, который в основном имитирует все это. В этом случае проще внедрить другую реализацию WebSocket, чем использовать насмешку.
Если это поможет, это базовая схема класса SyncedDOMMOdel:
public class SyncedDOMMOdel {
....
@Inject
public SyncedDOMModel(WebSocket socket){
this.socket = socket;
}
....
}
1 ответ
Вы можете использовать GinModuleAdapter
использовать любой GinModule
как Guice Module
,
Очевидно, что вы не сможете воспользоваться специфическими функциями GIN: по умолчанию GWT.create()
когда что-то не имеет конкретной привязки (это включает интерфейсы и абстрактные классы, которые будут выбрасывать в Guice), и автоматически искать RemoteService
интерфейс, когда интерфейс, имя которого заканчивается Async
не имеет конкретной привязки.
И вы не сможете использовать что-либо, что зависит от JSNI или отложенной привязки (GWT.create()
), как в любомGWTTestCase
модульный тест.