单元测试网络响应。调试时有效,实际时无效 运行
Unit testing a network response. Works when debugging, not when actually running
我目前正在尝试测试是否确实收到了网络响应。
虽然我明白这不是我应该做的关于测试的事情,但这是我自愿的好奇心,如果可能的话我想继续.
就目前而言,我已经成功创建了测试。请求被毫无问题地发送到 volley 队列。
现在奇数部分:
该请求永远不会执行。这是我如何测试它的想法:
@Test
public void testSimpleGetResponseFromServerVolley() throws Exception {
final CountDownLatch signal = new CountDownLatch(1);
NetworkClass.NetworkListener listener = new NetworkClass.NetworkListener() {
@Override
public void onResponse(Response response) {
assertThat(response != null);
System.out.println("Got Response");
signal.countDown();
}
@Override
public void onError(Throwable error) {
System.out.println("No Response");
signal.countDown();
}
};
NetworkClass.getResponseFromServer(null, listener);
signal.await();
}
此代码意外导致测试挂起且永远无法完成。
然而,这是我停止对情况失去理解的地方:
如果我 运行 通过 debug 测试并逐行执行,测试成功执行,并收到响应。
我认为发生了什么:
当我通过调试单步执行时,volley requestQueue 成功进行并发出请求,并在调用 await()
之前收到响应。
当我没有通过调试单步执行时,await()
正在阻塞处理所有这些的线程。
关于如何处理这个问题有什么想法吗?
Volley 依靠 Looper.getMainLooper()
来处理它的执行。当使用 RobolectricTestRunner 时,Robolectric 模拟了这一点,因此它不会被正确设置,从而导致测试失败。
在我的具体情况下,当我使用断点时,系统实际上确实设置了主循环程序,因为系统正在利用它来显示断点/调试工具。因此,这描述了我最初问题中发现的行为背后的原因。
现在对于在单元测试期间使用 Volley 获得真实网络响应的解决方案,必须将执行程序更改为不使用主循环程序。
作为一个简单的解决方案,创建一个依赖于 Executor.singleThreadExecutor()
而不是 Main Looper 的请求队列。
我的意思是:
//Specific test queue that uses a singleThreadExecutor instead of the mainLooper for testing purposes.
public RequestQueue newVolleyRequestQueueForTest(final Context context) {
File cacheDir = new File(context.getCacheDir(), "cache/volley");
Network network = new BasicNetwork(new HurlStack());
ResponseDelivery responseDelivery = new ExecutorDelivery(Executors.newSingleThreadExecutor());
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network, 4, responseDelivery);
queue.start();
return queue;
}
然后,在测试期间将其用作 Volley 的请求队列。
这里的关键是:
ResponseDelivery responseDelivery = new ExecutorDelivery(Executors.newSingleThreadExecutor());
希望对您有所帮助!
我目前正在尝试测试是否确实收到了网络响应。
虽然我明白这不是我应该做的关于测试的事情,但这是我自愿的好奇心,如果可能的话我想继续.
就目前而言,我已经成功创建了测试。请求被毫无问题地发送到 volley 队列。
现在奇数部分:
该请求永远不会执行。这是我如何测试它的想法:
@Test
public void testSimpleGetResponseFromServerVolley() throws Exception {
final CountDownLatch signal = new CountDownLatch(1);
NetworkClass.NetworkListener listener = new NetworkClass.NetworkListener() {
@Override
public void onResponse(Response response) {
assertThat(response != null);
System.out.println("Got Response");
signal.countDown();
}
@Override
public void onError(Throwable error) {
System.out.println("No Response");
signal.countDown();
}
};
NetworkClass.getResponseFromServer(null, listener);
signal.await();
}
此代码意外导致测试挂起且永远无法完成。
然而,这是我停止对情况失去理解的地方:
如果我 运行 通过 debug 测试并逐行执行,测试成功执行,并收到响应。
我认为发生了什么:
当我通过调试单步执行时,volley requestQueue 成功进行并发出请求,并在调用 await()
之前收到响应。
当我没有通过调试单步执行时,await()
正在阻塞处理所有这些的线程。
关于如何处理这个问题有什么想法吗?
Volley 依靠 Looper.getMainLooper()
来处理它的执行。当使用 RobolectricTestRunner 时,Robolectric 模拟了这一点,因此它不会被正确设置,从而导致测试失败。
在我的具体情况下,当我使用断点时,系统实际上确实设置了主循环程序,因为系统正在利用它来显示断点/调试工具。因此,这描述了我最初问题中发现的行为背后的原因。
现在对于在单元测试期间使用 Volley 获得真实网络响应的解决方案,必须将执行程序更改为不使用主循环程序。
作为一个简单的解决方案,创建一个依赖于 Executor.singleThreadExecutor()
而不是 Main Looper 的请求队列。
我的意思是:
//Specific test queue that uses a singleThreadExecutor instead of the mainLooper for testing purposes.
public RequestQueue newVolleyRequestQueueForTest(final Context context) {
File cacheDir = new File(context.getCacheDir(), "cache/volley");
Network network = new BasicNetwork(new HurlStack());
ResponseDelivery responseDelivery = new ExecutorDelivery(Executors.newSingleThreadExecutor());
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network, 4, responseDelivery);
queue.start();
return queue;
}
然后,在测试期间将其用作 Volley 的请求队列。
这里的关键是:
ResponseDelivery responseDelivery = new ExecutorDelivery(Executors.newSingleThreadExecutor());
希望对您有所帮助!