:)
我遇到了使用 Volley 模拟网络异常的问题。我的想法是"模拟"一个总是会抛出异常的网络类。然后在我的 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 {
...
}
}
});
}
MyManagercreateSession(..)
方法只是创建一个JsonObjectRequest
的新实例,并在收到响应时调用OnResponseReceivedListener
的方法。
当我运行测试时,永远不会调用回调方法(JSONObjectRequest 中的方法,当然还有侦听器中的方法)。
知道为什么吗?我错过了什么吗?也许整个方法都是错误的?
谢谢很多人!
编辑
我也尝试用这new RequestQueue(...)
行替换mMainRequestQueue = new RequestQueue(new NoCache(), mMockedNetwork, 4,new ExecutorDelivery(Executors.newSingleThreadExecutor()));
相同的结果。
编辑 2
正如David Wallace所提到的,该方法是从一个名为NetworkDispatcher的Volley库类中调用
的。....
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;
}
...
networkDispatchers是在RequestQueue中创建的,使用"mocked"对象作为参数。所以我希望调用该方法。
在@Before
方法中,启动RequestQueue
线程,该线程又调用performRequest
。 稍后,在@Test
方法中,您将存根performRequest
方法 - 也就是说,指定调用performRequest
时应发生的情况。
但这会产生竞争条件。 此测试的行为是不确定的,因为我们无法判断RequestQueue
线程是否会在该调用存根之前或之后到达对performRequest
的调用。 因此,您可能会获得该方法的原始版本,或者您可能会获得存根版本。 确定的唯一方法是重新设计测试的工作方式。
您确实需要先存根performRequest
,然后启动RequestQueue
线程。 可能最简单的做法是在完成所有存根后,将mMainRequestQueue.start();
向下移动到@Test
方法中。