Я пытаюсь написать тест JUnit для службы Android с помощью RoboGuice 2.0. У меня есть тестовый модуль, который связывает вложенные зависимости с Mockito mock objects. Тем не менее, когда я запускаю тест, вместо него вводят реальные реализации из моего модуля приложения. Вот некоторые из соответствующего кода:Модуль модульного тестирования RoboGuice вместо тестового модуля
MainApplication.java:
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
RoboGuice.setBaseApplicationInjector(this, RoboGuice.DEFAULT_STAGE,
RoboGuice.newDefaultRoboModule(this), new MainModule());
startService(new Intent(this, NotificationService.class));
}
}
MainModule.java:
public class MainModule extends AbstractModule {
@Override
protected void configure() {
bind(IFooManager.class).to(FooManagerImpl.class).in(Scopes.SINGLETON);
}
}
NotificationService.java:
public class NotificationService extends RoboService {
@Inject
private NotificationManager notificationManager;
@Inject
private SharedPreferences prefs;
@Inject
private IFooManager fooManager;
private IFooListener listener = new FooListener();
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
fooManager.addListener(listener);
}
@Override
public void onDestroy() {
super.onDestroy();
fooManager.removeListener(listener);
}
private class FooListener implements IFooListener {
// Do stuff that fires Notifications
}
}
NotificationServiceTest.java:
public class NotificationServiceTest extends ServiceTestCase<NotificationService> {
@Mock
private MockFooManager fooManager;
@Mock
private MockSharedPreferences prefs;
public NotificationServiceTest() {
super(NotificationService.class);
}
public void testStart() {
startService(null);
verify(fooManager).addListener(isA(IFooListener.class));
}
public void testStop() {
shutdownService();
verify(fooManager).removeListener(isA(IFooListener.class));
}
@Override
protected void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
Application app = new MockApplication();
setApplication(app);
RoboGuice.setBaseApplicationInjector(app, RoboGuice.DEFAULT_STAGE, new TestModule());
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
RoboGuice.util.reset();
}
private class TestModule extends AbstractModule {
@Override
protected void configure() {
bind(Context.class).toInstance(getContext());
bind(IFooManager.class).toInstance(fooManager);
bind(SharedPreferences.class).toInstance(prefs);
}
}
}
MockFooManager и MockSharedPreferences - пустые абстрактные реализации IFooManager и SharedPreferences, необходимые, потому что RoboGuice can't inject mocks of interfaces. Я использую Mockito с Dexmaker для поддержки генерации байт-кода для издевающихся классов. Кроме того, я не использую Robolectric, я запускаю эти тесты на устройстве или в эмуляторе.
Когда я запускаю этот тест, я получаю сообщение об ошибке Wanted but not invoked: fooManager.addListener(isA(com.example.IFooListener))
. После того, как вы перешли через это с помощью отладчика, я обнаружил, что RoboGuice вводит зависимости от MainModule вместо TestModule, поэтому тест использует FooManagerImpl вместо MockFooManager. Я не понимаю, как RoboGuice знает о MainModule в тестовом коде.
Вот некоторые другие вещи, которые я пытался это исправить, но ни один не имел никакого эффекта:
- Specify модули приложения в
roboguice.xml
вместо вызоваRoboGuice.setBaseApplicationInjector
вMainApplication.onCreate
- Использование
Modules.override
при вызовеRoboGuice.setBaseApplicationInjector
вместо проездом список модулей напрямую.
Как заставить RoboGuice использовать TestModule и игнорировать MainModule в своем модульном тесте?