单元测试网络响应.调试时工作,而不是实际运行时

Vic*_*cVu 9 junit android mockito android-networking android-testing

我目前正在尝试测试实际收到的网络响应.

虽然我知道这不是我应该在测试方面做的事情,但我对自己的意志充满了好奇心,如果可能的话我想继续.

就目前而言,我已成功创建了测试.请求将毫无问题地发送到排队队列.

现在奇怪的部分:

该请求永远不会执行.这是我如何测试它的想法:

 @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();
    }
Run Code Online (Sandbox Code Playgroud)

此代码意外地导致测试挂起并且永远不会完成.

然而,这是我不再理解这种情况的地方:

如果我通过调试运行测试并逐行执行,则测试成功执行,并收到响应.

我认为发生了什么:

当我逐步通过调试时,凌空requestQueue成功继续并发出请求,并在await()调用之前接收响应.

当我不通过调试步进时,await()阻塞处理所有这一切的线程.

关于如何处理这个问题的任何想法?

Vic*_*cVu 8

Volley依赖于Looper.getMainLooper()处理它的执行.当使用RobolectricTestRunner时,Robolectric会将其嘲弄,因此无法正确设置,从而导致测试失败.

在我的具体情况下,当我使用断点时,系统实际上确实设置了主循环器,因为系统正在利用它来显示断点/调试工具.这因此描述了我在初始问题中发现的行为背后的原因.

现在,对于在单元测试期间使用Volley获得真实网络响应的解决方案,必须将执行程序更改为不使用主循环器.

作为一个简单的解决方案,创建一个依赖于Executor.singleThreadExecutor()主循环器而不是主循环器的请求队列.

这就是我的意思:

    //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;
}
Run Code Online (Sandbox Code Playgroud)

然后,在测试期间将其用作Volley的请求队列.

这里的关键是:

ResponseDelivery responseDelivery = new ExecutorDelivery(Executors.newSingleThreadExecutor());

希望这可以帮助!