在空闲资源繁忙时测试 UI
Test UI while idling resource is busy
我是 android 测试的新手,我 运行 遇到了问题。我正在使用 RxJava 并测试 UI 我正在使用 IdlingResource。虽然空闲资源很忙,但我无法测试 UI。
例如:我有一个按钮。 onClick 我正在做一个请求。在请求按钮禁用时。请求后按钮处于启用状态。我想测试以下 3 个步骤:
- 按钮在请求之前启用
- 请求时按钮被禁用 (onCLick)
- 请求结束和响应消息时启用按钮returns
如果你能在这个问题上帮助我,我将非常高兴...
如果您需要有关我的问题的更多信息,请告诉我。我会编辑我的 post
据我了解,您正在尝试测试您的 UI。如果是这样,请确保您以正确的方式进行操作:
1). 你没有做 REAL 请求。
请理解,您的测试在类似情况下必须始终具有相同的行为。换句话说,它必须给出 相同的结果,你传递相同的输入参数。
您现在的输入参数:
1.1).按钮在请求前启用
1.2).请求期间禁用按钮
1.3).请求后启用的按钮
从这个列表可以看出,您不需要做真正的请求。对你来说没关系,什么服务器会 return 你(错误或成功)。您甚至不需要服务器。您所需要的只是 "something",它的行为就像一个真正的服务器。换句话说,你必须模拟你的 API 客户端。
我想你正在使用改造。如果不是,您必须为您的客户创建 interface
包装器。如果你正在使用改造,你只需要模拟你的 interface
.
假设您有下一个 interface
:
public interface ApiClient{
@GET("/items")
Observable<MyResponse> doSomeRequest();
}
您通常如何创建 API 客户端:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
ApiClient service = retrofit.create(ApiClient.class);
你应该如何在测试中做到这一点:
import static org.mockito.Mockito.*;
并在测试方法中:
ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest())
.thenReturn(Observable.just(fakeResponse));
或
ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest())
.thenReturn(Observable.defer(new Func0<Observable<MyResponse>>() {
@Override
public Observable<MyResponse> call() {
try{
Thread.sleep(2 * 1000) //2 seconds
}catch(Exception e){
return Observable.error(e);
}
return Observable.just(fakeResponse);
}
}));
P.S. Retrofit 默认将 .subscribeOn(Schedulers.io())
添加到所有 Observable
。这个模拟对象不这样做。所以,请不要忘记在您的代码中添加 .subscribeOn(Schedulers.io())
,或将其应用于 Observable.defer(...)
的结果
在上面的代码中,它看起来像:
when(apiMock.doSomeRequest())
.thenReturn(Observable.defer(...).subscribeOn(Schedulers.io()));
并且您应该将 apiMock
传递给您尝试测试的 Activity
/ Fragment
。
怎么做? 参见#2。
2).使用DI(依赖注入)
我不会写太多。
我只是建议您阅读 http://google.github.io/dagger/
上的文档
尤其是如何组织项目,何时可以使用真实实现进行生产,何时可以使用模拟实现进行测试:
http://google.github.io/dagger/testing.html
换句话说,当您要构建应用程序供使用时,您提供了真正的依赖项(在您的情况下,它将是 ApiClient
的真正实现),并且当您要测试一些UI 或业务逻辑,您传递模拟依赖项,这些依赖项具有您在测试前指定的行为。
这就是我想告诉你的全部。希望这对您有所帮助,如果您有任何其他问题,请告诉我。
的小补充。我会为 "mocked" api 使用 Subject
。这允许您控制执行。
//setup your test
Subject<Response,Response> stubResponse = AsyncSubject.create();
ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest()).thenReturn(stubResponse.asObservable());
//check first condition that button is enabled before executing action
//click on button
//test your second condition that button is disabled while waiting for response
stubResponse.onNext(fakeResponse); //return fake response
stubResponse.onCompleted();
//test your third condition that button is enabled when you get response back
备注。切勿在测试中使用 sleep
。它会减慢你的测试并增加片状。
我是 android 测试的新手,我 运行 遇到了问题。我正在使用 RxJava 并测试 UI 我正在使用 IdlingResource。虽然空闲资源很忙,但我无法测试 UI。
例如:我有一个按钮。 onClick 我正在做一个请求。在请求按钮禁用时。请求后按钮处于启用状态。我想测试以下 3 个步骤:
- 按钮在请求之前启用
- 请求时按钮被禁用 (onCLick)
- 请求结束和响应消息时启用按钮returns
如果你能在这个问题上帮助我,我将非常高兴...
如果您需要有关我的问题的更多信息,请告诉我。我会编辑我的 post
据我了解,您正在尝试测试您的 UI。如果是这样,请确保您以正确的方式进行操作:
1). 你没有做 REAL 请求。
请理解,您的测试在类似情况下必须始终具有相同的行为。换句话说,它必须给出 相同的结果,你传递相同的输入参数。
您现在的输入参数:
1.1).按钮在请求前启用
1.2).请求期间禁用按钮
1.3).请求后启用的按钮
从这个列表可以看出,您不需要做真正的请求。对你来说没关系,什么服务器会 return 你(错误或成功)。您甚至不需要服务器。您所需要的只是 "something",它的行为就像一个真正的服务器。换句话说,你必须模拟你的 API 客户端。
我想你正在使用改造。如果不是,您必须为您的客户创建 interface
包装器。如果你正在使用改造,你只需要模拟你的 interface
.
假设您有下一个 interface
:
public interface ApiClient{
@GET("/items")
Observable<MyResponse> doSomeRequest();
}
您通常如何创建 API 客户端:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
ApiClient service = retrofit.create(ApiClient.class);
你应该如何在测试中做到这一点:
import static org.mockito.Mockito.*;
并在测试方法中:
ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest())
.thenReturn(Observable.just(fakeResponse));
或
ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest())
.thenReturn(Observable.defer(new Func0<Observable<MyResponse>>() {
@Override
public Observable<MyResponse> call() {
try{
Thread.sleep(2 * 1000) //2 seconds
}catch(Exception e){
return Observable.error(e);
}
return Observable.just(fakeResponse);
}
}));
P.S. Retrofit 默认将 .subscribeOn(Schedulers.io())
添加到所有 Observable
。这个模拟对象不这样做。所以,请不要忘记在您的代码中添加 .subscribeOn(Schedulers.io())
,或将其应用于 Observable.defer(...)
的结果
在上面的代码中,它看起来像:
when(apiMock.doSomeRequest())
.thenReturn(Observable.defer(...).subscribeOn(Schedulers.io()));
并且您应该将 apiMock
传递给您尝试测试的 Activity
/ Fragment
。
怎么做? 参见#2。
2).使用DI(依赖注入)
我不会写太多。
我只是建议您阅读 http://google.github.io/dagger/
尤其是如何组织项目,何时可以使用真实实现进行生产,何时可以使用模拟实现进行测试:
http://google.github.io/dagger/testing.html
换句话说,当您要构建应用程序供使用时,您提供了真正的依赖项(在您的情况下,它将是 ApiClient
的真正实现),并且当您要测试一些UI 或业务逻辑,您传递模拟依赖项,这些依赖项具有您在测试前指定的行为。
这就是我想告诉你的全部。希望这对您有所帮助,如果您有任何其他问题,请告诉我。
Subject
。这允许您控制执行。
//setup your test
Subject<Response,Response> stubResponse = AsyncSubject.create();
ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest()).thenReturn(stubResponse.asObservable());
//check first condition that button is enabled before executing action
//click on button
//test your second condition that button is disabled while waiting for response
stubResponse.onNext(fakeResponse); //return fake response
stubResponse.onCompleted();
//test your third condition that button is enabled when you get response back
备注。切勿在测试中使用 sleep
。它会减慢你的测试并增加片状。