模拟排球网络以模拟网络错误

时间:2014-02-06 12:42:06

标签: android mocking mockito robolectric android-volley

:)

我正面临使用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;
            }
...

networkDispatcher是在RequestQueue中创建的,使用“mocked”对象作为参数。所以我希望调用这个方法。

1 个答案:

答案 0 :(得分:1)

@Before方法中,您启动RequestQueue主题,然后调用performRequest。稍后,在@Test方法中,您将performRequest方法存根 - 即指定调用performRequest时应发生的情况。

但是这会造成竞争条件。此测试的行为是不确定的,因为我们无法判断RequestQueue线程是否会在该调用被截断之前或之后到达performRequest的调用。因此,您可能会获得该方法的原始版本,或者您可能会获得该存根版本。唯一可以确定的方法是重新设计测试的工作方式。

您确实需要首先存根performRequest,然后启动您的RequestQueue主题。可能最简单的做法是在完成所有存根之后将mMainRequestQueue.start();向下移动到@Test方法。