:)

我在使用Volley模拟网络异常时遇到问题。我的想法是“模拟”将始终引发异常的Network类。然后在我的RequestQueue中使用该网络,并测试在引发网络异常时我的DataManager(MyManager)的行为。我知道这种方法可能并不完全正确,但是我希望我可以知道一种更好的方法来实现我的UnitTest案例。

顺便说一下,我使用Robolectric 2.2和Mockito 1.9.5。让我们深入研究代码:

RequestQueue mMainRequestQueue;
private Network mMockedNetwork;

@Before
public void setup(){
    Robolectric.getFakeHttpLayer().interceptHttpRequests(false);

    ShadowLog.stream = System.out;
    mMockedNetwork = spy(new BasicNetwork(new HurlStack()));
    mMainRequestQueue = new RequestQueue(new NoCache(), mMockedNetwork);
    mMainRequestQueue.start();
}

@Test
public void testLogin() throws Exception {

    doThrow(new VolleyError()).when(mMockedNetwork).performRequest(any(JsonObjectRequest.class));

    MyManager.getInstance(Robolectric.application.getApplicationContext()).setMainQueue(mMainRequestQueue);
    MyManager.getInstance(Robolectric.application.getApplicationContext()).createSession("sessionId", "date", new MyManager.OnResponseReceivedListener() {
        @Override
        public void responseReceived(boolean error, Object responseObject) {
            if (error) {
                ...
            } else {
                ...
            }
        }
    });

}


MyManager createSession(..)方法仅创建JsonObjectRequest的新实例,并在收到响应时调用OnResponseReceivedListener的方法。

当我运行测试时,永远不会调用回调方法(JSONObjectRequest中的方法,当然还有侦听器中的方法)。

知道为什么吗?我想念什么吗?也许整个方法是错误的?

非常感谢大家!

编辑

我也尝试用此new RequestQueue(...)替换mMainRequestQueue = new RequestQueue(new NoCache(), mMockedNetwork, 4,new ExecutorDelivery(Executors.newSingleThreadExecutor()));

结果相同。

编辑2

正如David Wallace所提到的那样,该方法是从Volley库类(称为NetworkDispatcher Here is the link)中调用的

....
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
            }

            // Perform the network request.
            NetworkResponse networkResponse = mNetwork.performRequest(request);
            request.addMarker("network-http-complete");

            // If the server returned 304 AND we delivered a response already,
            // we're done -- don't deliver a second identical response.
            if (networkResponse.notModified && request.hasHadResponseDelivered()) {
                request.finish("not-modified");
                continue;
            }
...


使用“模拟”对象作为参数在requestQueue中创建networkDispatchers。因此,我希望可以调用该方法。

最佳答案

在您的@Before方法中,启动RequestQueue线程,该线程又调用performRequest。稍后,在您的@Test方法中,对performRequest方法进行存根-也就是说,您指定调用performRequest时应发生的情况。

但这创造了竞争条件。该测试的行为是不确定的,因为我们无法确定RequestQueue线程是在存根调用之前还是之后都到达了对performRequest的调用。因此,您可能会获得该方法的原始版本,也可能会获得存根版本。确保唯一的方法是重新设计测试的工作方式。

您确实需要先对performRequest进行存根,然后启动RequestQueue线程。可能最简单的事情是在完成所有存根之后将mMainRequestQueue.start();向下移动到@Test方法中。

10-08 14:50