J'essaie d'écrire un test JUnit pour un service Android en utilisant RoboGuice 2.0. J'ai un module de test qui lie les dépendances injectées aux objets fantaisie de Mockito. Cependant, lorsque je lance le test, les implémentations réelles de mon module d'application sont injectées à la place. Voici une partie du code concerné :
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 et MockSharedPreferences sont des implémentations abstraites vides de IFooManager et SharedPreferences, nécessaires car RoboGuice ne peut pas injecter des objets fantaisie d'interfaces. . J'utilise Mockito avec Dexmaker pour prendre en charge la génération de bytecode pour les classes simulées. De plus, je n'utilise pas Robolectric, j'exécute ces tests sur un appareil ou dans l'émulateur.
Lorsque j'exécute ce test, j'obtiens l'erreur suivante Wanted but not invoked: fooManager.addListener(isA(com.example.IFooListener))
. Après avoir parcouru tout cela avec le débogueur, j'ai découvert que RoboGuice injecte les dépendances de MainModule au lieu de TestModule, donc le test utilise FooManagerImpl au lieu de MockFooManager. Je ne comprends pas comment RoboGuice peut connaître MainModule dans le code de test.
Voici d'autres choses que j'ai essayées pour résoudre ce problème, mais aucune n'a eu d'effet :
- Spécifiez les modules d'application dans
roboguice.xml
au lieu d'appelerRoboGuice.setBaseApplicationInjector
enMainApplication.onCreate
- Utilisez
Modules.override
lors de l'appelRoboGuice.setBaseApplicationInjector
au lieu de passer directement la liste des modules.
Comment faire pour que RoboGuice utilise TestModule et ignore MainModule dans mon test unitaire ?