2013-05-06 1 views
5

Я пытаюсь написать тест 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 в своем модульном тесте?

ответ

0

Похоже, что вам не хватает вызова, чтобы выполнить инъекцию в вашем NotificationServiceTest. Это делается следующим образом:

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

Вам нужно будет добавить это в какой-то момент после того, как вы установите базовый инжектор и перед запуском тестов.

0

Использование

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

вместо

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