2013-05-06 18 views
5

Próbuję napisać test JUnit dla usługi Android za pomocą RoboGuice 2.0. Mam moduł testowy, który łączy wstrzyknięte zależności z fałszywymi obiektami Mockito. Jednak po uruchomieniu testu zamiast tego zostaną wprowadzone prawdziwe implementacje z mojego modułu aplikacji. Oto niektóre z odpowiednim kodem:Moduł testowy modułu RoboGuice do wstrzykiwania zamiast modułu testowego

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 i MockSharedPreferences to puste abstrakcyjne implementacje IFooManagera i SharedPreferences, potrzebne z powodu RoboGuice can't inject mocks of interfaces. Używam Mockito z Dexmaker do wspierania generowania kodu bajtowego dla wyśmiewanych klas. Ponadto, nie używam Robolectric, uruchamiam te testy na urządzeniu lub emulatorze.

Po uruchomieniu tego testu pojawia się błąd Wanted but not invoked: fooManager.addListener(isA(com.example.IFooListener)). Po przejściu przez to z debuggerem, stwierdziłem, że RoboGuice wstrzykuje zależności z MainModule zamiast z TestModule, więc test używa FooManagerImpl zamiast MockFooManagera. Nie rozumiem, jak RoboGuice wie o MainModule w kodzie testowym.

Oto kilka innych rzeczy, próbowałem to naprawić, ale żaden nie miał żadnego wpływu:

  • Określanie modułów aplikacji w roboguice.xml zamiast dzwonić RoboGuice.setBaseApplicationInjector w MainApplication.onCreate
  • Zastosowanie Modules.override Dzwoniąc RoboGuice.setBaseApplicationInjector zamiast tylko przejazdem bezpośrednio na liście modułów.

Co zrobić, aby RoboGuice używał modułu testowego i ignorował moduł główny w moim teście urządzenia?

Odpowiedz

0

Wygląda na to, że brakuje telefonu do wykonania wstrzyknięcia w swoim Testie usługi powiadomień. Wykonuje się to w następujący sposób:

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

Będziesz musiał dodać to w pewnym momencie po ustawieniu wtryskiwacza podstawowego i przed uruchomieniem testów.

0

Zastosowanie

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

zamiast

RoboGuice.setBaseApplicationInjector(app, RoboGuice.DEFAULT_STAGE, new TestModule()); 
Powiązane problemy