2013-05-06 15 views
5

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 chiamare RoboGuice.setBaseApplicationInjector in MainApplication.onCreate
  • Usa Modules.override al momento della chiamata RoboGuice.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à?

risposta

0

Sembra che manchi una chiamata per eseguire l'iniezione nel NotificationServiceTest. Questo viene fatto come segue:

RoboGuice.getInjector(app).injectMembers(this); 

Sarà necessario aggiungere questo ad un certo punto dopo aver impostato l'iniettore di base e prima che i test vengono eseguiti.

0

Usa

RoboGuice.overrideApplicationInjector(app,RoboGuice.newDefaultRoboModule(app), new TestModule()) 

invece di

RoboGuice.setBaseApplicationInjector(app, RoboGuice.DEFAULT_STAGE, new TestModule());