2014-10-29 5 views
2

대검을 통해 다른 객체를 테스트 또는 생산 여부에 따라 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 protected]"); // this will start the service 
     wait_hack(); // This makes the test wait for the reposen form the intentservice, works fine 
     DBHelper.isUserRegisterd("[email protected]")); 
    } 

}

테스트 실행 성공적인은 (코드가 simplyfied되고, 기억 수도 시도 컴파일하지 않고, 단지 그 아이디어를 표현해야한다). 그러나 Mocked가 아닌 "실제"WebRequest Impl.을 계속 사용합니다. 서버에서 로그, 프록시 및 ourse의 내용을 볼 수 있습니다.

RoboGuice를 사용하여 매우 비슷한 방식으로이 작업을 수행했습니다. 그러나 어쨌든 나는 이것을 단검으로 처리 할 수 ​​없습니다. (현재 DI 프레임 워크를 평가 중이며 "필수"임)

답변

0

plus 메서드는 실제 새 그래프를 반환합니다. 원래 그래프를 덮어 쓰지 않습니다. 당신이 원하는 것을 성취한다고 말하면서 간단히 할 수 있습니다.

public class MainApplication extends Application { 

    ... 

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

이것은 원래의 그래프를 가져 와서 새 모듈로 추가 한 다음 새 그래프를 mObjectGraph 참조에 지정하기 만하면됩니다.

+0

"새 그래프를 반환합니다"라는 말이 맞고 조정했지만 문제가 해결되지 않습니다. 이 테스트는 여전히 WebRequest의 "프로덕션"구현을 사용하고 있습니다. – Christoph

+0

어딘가에 제대로 연결되지 않은 뭔가가 있다고 가정하고 있지만 코드에 문제가있는 것을 볼 수 없습니다. 개인적으로이 접근법을 ServiceTestCase에 사용하고 MockModule로 그래프를 재정의하면 모든 것이 잘 작동합니다. –

+0

나는 다음날 DI에 대해 좀 더 연구 할 것이다. 내가 틀린 것을 발견하면, 나는이 주제로 돌아갈 것이다. – Christoph