/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.volley; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; import com.android.volley.Request.Priority; import com.android.volley.RequestQueue.RequestFinishedListener; import com.android.volley.mock.MockRequest; import com.android.volley.mock.ShadowSystemClock; import com.android.volley.toolbox.NoCache; import com.android.volley.utils.ImmediateResponseDelivery; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; /** * Integration tests for {@link RequestQueue} that verify its behavior in conjunction with real * dispatcher, queues and Requests. * *

The Network is mocked out. */ @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowSystemClock.class}) public class RequestQueueIntegrationTest { private ResponseDelivery mDelivery; @Mock private Network mMockNetwork; @Mock private RequestFinishedListener mMockListener; @Mock private RequestFinishedListener mMockListener2; @Before public void setUp() throws Exception { mDelivery = new ImmediateResponseDelivery(); initMocks(this); } @Test public void add_requestProcessedInCorrectOrder() throws Exception { // Enqueue 2 requests with different cache keys, and different priorities. The second, // higher priority request takes 20ms. // Assert that the first request is only handled after the first one has been parsed and // delivered. MockRequest lowerPriorityReq = new MockRequest(); MockRequest higherPriorityReq = new MockRequest(); lowerPriorityReq.setCacheKey("1"); higherPriorityReq.setCacheKey("2"); lowerPriorityReq.setPriority(Priority.LOW); higherPriorityReq.setPriority(Priority.HIGH); Answer delayAnswer = new Answer() { @Override public NetworkResponse answer(InvocationOnMock invocationOnMock) throws Throwable { Thread.sleep(20); return mock(NetworkResponse.class); } }; // delay only for higher request when(mMockNetwork.performRequest(higherPriorityReq)).thenAnswer(delayAnswer); when(mMockNetwork.performRequest(lowerPriorityReq)).thenReturn(mock(NetworkResponse.class)); RequestQueue queue = new RequestQueue(new NoCache(), mMockNetwork, 1, mDelivery); queue.addRequestFinishedListener(mMockListener); queue.add(lowerPriorityReq); queue.add(higherPriorityReq); queue.start(); InOrder inOrder = inOrder(mMockListener); // verify higherPriorityReq goes through first inOrder.verify(mMockListener, timeout(10000)).onRequestFinished(higherPriorityReq); // verify lowerPriorityReq goes last inOrder.verify(mMockListener, timeout(10000)).onRequestFinished(lowerPriorityReq); queue.stop(); } /** Asserts that requests with same cache key are processed in order. */ @Test public void add_dedupeByCacheKey() throws Exception { // Enqueue 2 requests with the same cache key. The first request takes 20ms. Assert that the // second request is only handled after the first one has been parsed and delivered. MockRequest req1 = new MockRequest(); MockRequest req2 = new MockRequest(); Answer delayAnswer = new Answer() { @Override public NetworkResponse answer(InvocationOnMock invocationOnMock) throws Throwable { Thread.sleep(20); return mock(NetworkResponse.class); } }; // delay only for first when(mMockNetwork.performRequest(req1)).thenAnswer(delayAnswer); when(mMockNetwork.performRequest(req2)).thenReturn(mock(NetworkResponse.class)); RequestQueue queue = new RequestQueue(new NoCache(), mMockNetwork, 3, mDelivery); queue.addRequestFinishedListener(mMockListener); queue.add(req1); queue.add(req2); queue.start(); InOrder inOrder = inOrder(mMockListener); // verify req1 goes through first inOrder.verify(mMockListener, timeout(10000)).onRequestFinished(req1); // verify req2 goes last inOrder.verify(mMockListener, timeout(10000)).onRequestFinished(req2); queue.stop(); } /** Verify RequestFinishedListeners are informed when requests are canceled. */ @Test public void add_requestFinishedListenerCanceled() throws Exception { MockRequest request = new MockRequest(); Answer delayAnswer = new Answer() { @Override public NetworkResponse answer(InvocationOnMock invocationOnMock) throws Throwable { Thread.sleep(200); return mock(NetworkResponse.class); } }; RequestQueue queue = new RequestQueue(new NoCache(), mMockNetwork, 1, mDelivery); when(mMockNetwork.performRequest(request)).thenAnswer(delayAnswer); queue.addRequestFinishedListener(mMockListener); queue.start(); queue.add(request); request.cancel(); verify(mMockListener, timeout(10000)).onRequestFinished(request); queue.stop(); } /** Verify RequestFinishedListeners are informed when requests are successfully delivered. */ @Test public void add_requestFinishedListenerSuccess() throws Exception { MockRequest request = new MockRequest(); RequestQueue queue = new RequestQueue(new NoCache(), mMockNetwork, 1, mDelivery); queue.addRequestFinishedListener(mMockListener); queue.addRequestFinishedListener(mMockListener2); queue.start(); queue.add(request); verify(mMockListener, timeout(10000)).onRequestFinished(request); verify(mMockListener2, timeout(10000)).onRequestFinished(request); queue.stop(); } /** Verify RequestFinishedListeners are informed when request errors. */ @Test public void add_requestFinishedListenerError() throws Exception { MockRequest request = new MockRequest(); RequestQueue queue = new RequestQueue(new NoCache(), mMockNetwork, 1, mDelivery); when(mMockNetwork.performRequest(request)).thenThrow(new VolleyError()); queue.addRequestFinishedListener(mMockListener); queue.start(); queue.add(request); verify(mMockListener, timeout(10000)).onRequestFinished(request); queue.stop(); } }