2013-05-06 123 views
5

我正在尝试使用RoboGuice 2.0为Android服务编写JUnit测试。我有一个测试模块,将注入的依赖关系绑定到Mockito模拟对象。但是,当我运行测试时,我的应用程序模块的实际实现会被注入。下面是一些相关的代码: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。

这里有一些其他的事情我试图解决这个问题,但没有任何效果:

  • 指定roboguice.xml应用模块,而不是在MainApplication.onCreate
  • 调用RoboGuice.setBaseApplicationInjector使用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());