Android Dagger在prod&;中向IntentService注入不同的依赖项;测试

Android Dagger在prod&;中向IntentService注入不同的依赖项;测试,android,unit-testing,dependency-injection,mockito,dagger,Android,Unit Testing,Dependency Injection,Mockito,Dagger,是否可以通过dagger将不同的对象注入android.app.IntentService,这取决于它是测试还是生产 这主要是将WebRequest类注入服务的代码(简化) public class SomeService extends android.app.IntentService { @Inject WebReqeust mWebRequest; public SomeService(String name) { super(name);

是否可以通过dagger将不同的对象注入android.app.IntentService,这取决于它是测试还是生产

这主要是将WebRequest类注入服务的代码(简化)

public class SomeService extends android.app.IntentService {

    @Inject 
    WebReqeust mWebRequest;

    public SomeService(String name) {
        super(name);
        MainApplication.getInstance().inject(this);
    } 

    @Override 
    protected void onHandleIntent(Intent intent) {
        String json = mWebRequest.getHttpString(url);
        JSONObject o = new JSONObject(json);
        DBHelper.insert(o);
    } 
}

@Module(injects = { SomeService.class })
    public class WebRequestModule {

    @Provides
    WebRequest provideWebRequest() {
        return new WebRequest();
    }
}

public class Modules {

    public static Object[] list() {
        return new Object[] {
            new WebRequestModule()
        };
    }
}

public class MainApplication extends Application {

    private ObjectGraph mOjectGraph;
    private static MainApplication sInstance;

    @Override
    public void onCreate() {
        sInstance = this;
        mOjectGraph = ObjectGraph.create(Modules.list());
    }

    public void inject(Object dependent) {
        mOjectGraph.inject(dependent);
    }

    public void addToGraph(Object module) {
        mOjectGraph.plus(module);
    }   
}
我想写一个模拟http响应的测试。 我从一个新模块开始

@Module(
        injects = SomeService.class,
        overrides = true
)
final class MockTestModule {
    @Provides
    WebRequest provideWebRequest() {
        WebRequest webRequest = mock(WebRequest.class);
            when(webRequest.getJSONObjectResponse(contains("/register/"))).thenReturn(
                    new JSONObject(FileHelper.loadJSONFromAssets(this.getClass(),     
                      "mock_register.json")));
            when(webRequest.getJSONObjectResponse(contains("/register_validate/"))).thenReturn(
                    new JSONObject(FileHelper.loadJSONFromAssets(this.getClass(),   
                      "mock_register_validate.json")));
        return webRequest;
    }
}
在测试中,我尝试了以下方法

public class RegisterTest extends AndroidTestCase {

    protected void setUp() throws Exception {
        MainApplication.getInstance().addToGraph(new MockTestModule());
        super.setUp();
    }

    public void test_theActuallTest() {
        Registration.registerUser("email@email.com"); // this will start the service
        wait_hack(); // This makes the test wait for the reposen form the intentservice, works fine
        DBHelper.isUserRegisterd("email@email.com"));
    }
}

测试成功执行(请记住,代码很简单,可能无法编译,只是应该表示想法)。 但是,它仍然使用“真实的”WebRequestImpl.,而不是模拟的WebRequestImpl。我在日志、代理和服务器上的ourse中看到它

我用一种非常相似的方式和RoboGuice一起做了这件事,而且效果很好。 但不知何故,我无法用匕首完成这件事。
(我目前正在评估DI框架,这是一个“必须具备的”)

方法实际返回新的图形。它不会覆盖原始图形。也就是说,要实现你想要的,你可以简单地做到这一点

public class MainApplication extends Application {

    ...

    // Mostly used for testing
    public void addToGraph(Object module) {
        mObjectGraph = mOjectGraph.plus(module);
    }   
}

这将获取原始图形并将其与新模块相加,然后简单地将新图形分配给mObjectGraph引用。

您的“返回新图形”是正确的,我对其进行了调整,但这并不能解决问题。测试仍在使用WebRequest的“生产”实现。我假设还有其他东西没有正确连接,但我看不出您的代码有任何错误。我个人在ServiceTestCase中使用了这种方法,并用MockModule覆盖了我的图形,一切都很好。我将在接下来的几天中对DI进行更多的研究。一旦我发现了问题所在,我就回到这个话题上来