Mar*_*kus 18 android unit-testing mockito robolectric retrofit
我有一个API接口,我正在测试View涉及网络调用.
@Config(emulateSdk = 18)
public class SampleViewTest extends RobolectricTestBase {
ServiceApi apiMock;
@Inject
SampleView fixture;
@Override
public void setUp() {
super.setUp(); //injection is performed in super
apiMock = mock(ServiceApi.class);
fixture = new SampleView(activity);
fixture.setApi(apiMock);
}
@Test
public void testSampleViewCallback() {
when(apiMock.requestA()).thenReturn(Observable.from(new ResponseA());
when(apiMock.requestB()).thenReturn(Observable.from(new ResponseB());
AtomicReference<Object> testResult = new AtomicReference<>();
fixture.updateView(new Callback() {
@Override
public void onSuccess(Object result) {
testResult.set(result);
}
@Override
public void onError(Throwable error) {
throw new RuntimeException(error);
}
});
verify(apiMock, times(1)).requestA();
verify(apiMock, times(1)).requestB();
assertNotNull(testResult.get());
}
}
Run Code Online (Sandbox Code Playgroud)
由于某种原因apiMock,从不调用方法,验证总是失败.
在我看来,我这样称呼我的api
apiV2.requestA()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer());
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么?
更新#1:
经过一些调查后,似乎在我的实施中(上面的示例)我observeOn(AndroidSchedulers.mainThread())没有调用订户.还是不知道为什么.
更新#2:
当订阅就像这样apiV2.requestA().subscribe(new Observer());一切正常 - 模拟api被调用并且测试通过.
前进ShadowLooper.idleMainLooper(5000)没有做任何事.甚至从处理程序中抓住了looper HandlerThreadScheduler并将其推进.结果相同.
更新#3: 添加使用API的实际代码.
public void updateView(final Callback) {
Observable.zip(wrapObservable(api.requestA()), wrapObservable(api.requestB()),
new Func2<ResponseA, ResponseB, Object>() {
@Override
public Object call(ResponseA responseA, ResponseB responseB) {
return mergeBothResponses(responseA, responseB);
}
}
).subscribe(new EndlessObserver<Object>() {
@Override
public void onError(Throwable e) {
Log.e(e);
listener.onError(e);
}
@Override
public void onNext(Object config) {
Log.d("Configuration updated [%s]", config.toString());
listener.onSuccess(config);
}
});
}
protected <T> Observable<T> wrapObservable(Observable<T> observable) {
return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
Run Code Online (Sandbox Code Playgroud)
Mig*_*gne 14
我仍在围绕如何正确使用rxjava,但我会尝试修改你的代码,以便你只在最终的压缩Observable上观察On(mainThread),而不是在原始请求响应的Observable上进行.然后我会验证这是否会影响你必须推进两个Loopers的事实.
为了简单地进行测试并消除对Looper空闲的需要,我会将线程从等式中取出,因为在运行测试时不需要后台处理.您可以通过注入Scheduler而不是静态创建它们来实现.在运行生产代码时,您需要注入AndroidSchedulers.mainThread和Schedulers.io,并且在运行测试代码时,您可以在适用的情况下注入Schedulers.immediate.
@Inject
@UIScheduler /* Inject Schedulers.immediate for tests and AndroidSchedulers.mainThread for production code */
private Scheduler mainThreadSched;
@Inject
@IOScheduler /* Inject Scheduler.immediate for tests and Schedulers.io for production code */
private Scheduler ioSched;
public void updateView(final Callback) {
Observable.zip(wrapObservable(api.requestA()), wrapObservable(api.requestB()),
new Func2<ResponseA, ResponseB, Object>() {
@Override
public Object call(ResponseA responseA, ResponseB responseB) {
return mergeBothResponses(responseA, responseB);
}
}
).observeOn(mainThreadSched)
.subscribe(new EndlessObserver<Object>() {
@Override
public void onError(Throwable e) {
Log.e(e);
listener.onError(e);
}
@Override
public void onNext(Object config) {
Log.d("Configuration updated [%s]", config.toString());
listener.onSuccess(config);
}
});
}
protected <T> Observable<T> wrapObservable(Observable<T> observable) {
return observable.subscribeOn(ioSched);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8775 次 |
| 最近记录: |