我正在尝试使用 RoboGuice 2.0 为 Android 服务编写 JUnit 测试。我有一个测试模块,它将注入的依赖项绑定到 Mockito 模拟对象。但是,当我运行测试时,我的应用程序模块中的真正实现会被注入。以下是一些相关代码:
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));
}
}
主模块.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 不能注入接口的模拟。我正在使用 Mockito 和 Dexmaker 来支持模拟类的字节码生成。另外,我没有使用 Robolectric,而是在设备或模拟器上运行这些测试。
当我运行这个测试时,我得到了错误Wanted but not invoked: fooManager.addListener(isA(com.example.IFooListener))
。在使用调试器逐步完成后,我发现 RoboGuice 是从 MainModule 而不是 TestModule 注入依赖项,因此测试使用的是 FooManagerImpl 而不是 MockFooManager。我不明白 RoboGuice 是如何知道测试代码中的 MainModule 的。
以下是我尝试解决的其他一些问题,但没有任何效果:
- 指定应用程序模块而
roboguice.xml
不是调用RoboGuice.setBaseApplicationInjector
MainApplication.onCreate
Modules.override
调用时使用,RoboGuice.setBaseApplicationInjector
而不是直接传递模块列表。
如何让 RoboGuice 在我的单元测试中使用 TestModule 并忽略 MainModule?