RoboGuice单元测试注入app模块而不是测试模块

sva*_*tom 5 junit android mockito android-service roboguice

我正在尝试使用RoboGuice 2.0为Android服务编写JUnit测试.我有一个测试模块,它将注入的依赖项绑定到Mockito模拟对象.但是,当我运行测试时,我的app模块的实际实现会被注入.以下是一些相关代码:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

MainModule.java:

public class MainModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(IFooManager.class).to(FooManagerImpl.class).in(Scopes.SINGLETON);
    }
}
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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.setBaseApplicationInjectorMainApplication.onCreate
  • Modules.override在调用时使用RoboGuice.setBaseApplicationInjector而不是直接传递模块列表.

如何让RoboGuice在我的单元测试中使用TestModule并忽略MainModule?

Sur*_*j C 0

您似乎缺少在NotificationServiceTest 中进行注入的调用。这是按如下方式完成的:

RoboGuice.getInjector(app).injectMembers(this);
Run Code Online (Sandbox Code Playgroud)

在设置基本注入器之后和运行测试之前,您需要在某个时候添加它。