Sto provando a scrivere un test JUnit per un servizio Android utilizzando RoboGuice 2.0. Ho un modulo di test che lega le dipendenze iniettate agli oggetti mockito mockito. Tuttavia, quando eseguo il test, vengono invece iniettate le reali implementazioni del modulo dell'app. Ecco parte del codice in questione:Test dell'unità RoboGuice che inietta il modulo dell'app al posto del modulo di test
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 e MockSharedPreferences sono implementazioni astratte vuote di IFooManager e SharedPreferences, necessarie perché RoboGuice can't inject mocks of interfaces. Sto usando Mockito con Dexmaker per supportare la generazione bytecode per le classi derise. Inoltre, non sto utilizzando Robolectric, sto eseguendo questi test su un dispositivo o nell'emulatore.
Quando si esegue questo test, viene visualizzato l'errore Wanted but not invoked: fooManager.addListener(isA(com.example.IFooListener))
. Dopo aver analizzato questo con il debugger, ho scoperto che RoboGuice sta iniettando le dipendenze da MainModule invece di TestModule, quindi il test sta utilizzando FooManagerImpl invece di MockFooManager. Non capisco come RoboGuice sia a conoscenza di MainModule nel codice di test.
Qui ci sono alcune altre cose che ho cercato di risolvere questo problema, ma nessuno ha avuto alcun effetto:
- specificare i moduli app in
roboguice.xml
invece di chiamareRoboGuice.setBaseApplicationInjector
inMainApplication.onCreate
- Usa
Modules.override
al momento della chiamataRoboGuice.setBaseApplicationInjector
invece che solo di passaggio la lista dei moduli direttamente.
Come posso ottenere da RoboGuice l'uso di TestModule e ignorare MainModule nel mio test dell'unità?