/* * Copyright (C) 2016 TIBCO Jaspersoft Corporation. All rights reserved. * http://community.jaspersoft.com/project/mobile-sdk-android * * Unless you have purchased a commercial license agreement from TIBCO Jaspersoft, * the following license terms apply: * * This program is part of TIBCO Jaspersoft Mobile SDK for Android. * * TIBCO Jaspersoft Mobile SDK is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * TIBCO Jaspersoft Mobile SDK is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with TIBCO Jaspersoft Mobile SDK for Android. If not, see * <http://www.gnu.org/licenses/lgpl>. */ package com.jaspersoft.android.sdk.service.repository; import com.jaspersoft.android.sdk.service.data.repository.Resource; import com.jaspersoft.android.sdk.service.data.repository.SearchResult; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; /** * @author Tom Koptel * @since 2.3 */ @RunWith(PowerMockRunner.class) @PrepareForTest({SearchUseCase.class}) public class RepositorySearchTaskV5_5Test { @Mock SearchUseCase mSearchUseCase; @Mock SearchResult mResponse; /** * Objects under test */ private RepositorySearchTask search10itemsStrategy; private RepositorySearchTask search10itemsStrategyWithUserOffset5; public static final List<Resource> FIVE_ITEMS = Arrays.asList(null, null, null, null, null); @Before public void setupMocks() throws Exception { MockitoAnnotations.initMocks(this); when(mSearchUseCase.performSearch(Matchers.any(InternalCriteria.class))).thenReturn(mResponse); InternalCriteria criteria = new InternalCriteria.Builder().limit(10).create(); search10itemsStrategy = new RepositorySearchTaskV5_5(criteria, mSearchUseCase); InternalCriteria userCriteria = criteria.newBuilder().offset(5).create(); search10itemsStrategyWithUserOffset5 = new RepositorySearchTaskV5_5(userCriteria, mSearchUseCase); } @Test public void willAlignResponseToLimitIfAPIRespondsWithPartialNumber() throws Exception { when(mResponse.getResources()).thenReturn(FIVE_ITEMS); Collection<Resource> result = search10itemsStrategy.nextLookup(); assertThat(result.size(), is(10)); InternalCriteria criteria1 = new InternalCriteria.Builder().limit(10).create(); verify(mSearchUseCase).performSearch(criteria1); InternalCriteria criteria2 = new InternalCriteria.Builder() .offset(10).limit(10).create(); verify(mSearchUseCase).performSearch(criteria2); } @Test public void willRetry5timesIfApiReturnsNoElements() throws Exception { when(mResponse.getResources()).thenReturn(Collections.<Resource>emptyList()); Collection<Resource> result = search10itemsStrategy.nextLookup(); assertThat(search10itemsStrategy.hasNext(), is(false)); assertThat(result, is(empty())); verify(mSearchUseCase, times(6)).performSearch(Matchers.any(InternalCriteria.class)); } @Test public void willReturnAsMuchElementsAsLeftIfEndReached() throws Exception { when(mResponse.getResources()).then(OnlyTwoItems.INSTANCE); Collection<Resource> result = search10itemsStrategy.nextLookup(); assertThat(result.size(), is(2)); verify(mSearchUseCase, times(6)).performSearch(Matchers.any(InternalCriteria.class)); } @Test public void forCustomOffsetShouldCalculateServerDisposition() throws Exception { when(mResponse.getResources()).thenReturn(FIVE_ITEMS); search10itemsStrategyWithUserOffset5.nextLookup(); InternalCriteria criteria1 = new InternalCriteria.Builder() .limit(5).create(); verify(mSearchUseCase).performSearch(criteria1); InternalCriteria criteria2 = new InternalCriteria.Builder() .limit(10).offset(5).create(); verify(mSearchUseCase).performSearch(criteria2); InternalCriteria criteria3 = new InternalCriteria.Builder() .limit(10).offset(15).create(); verify(mSearchUseCase).performSearch(criteria3); verify(mSearchUseCase, times(3)).performSearch(Matchers.any(InternalCriteria.class)); verifyNoMoreInteractions(mSearchUseCase); } @Test public void shouldReturnEmptyCollectionForZeroLimit() throws Exception { InternalCriteria userCriteria = new InternalCriteria.Builder().limit(0).offset(5).create(); RepositorySearchTask strategy = new RepositorySearchTaskV5_5(userCriteria, mSearchUseCase); List<Resource> result = strategy.nextLookup(); assertThat(result, is(empty())); verifyZeroInteractions(mSearchUseCase); } private static class OnlyTwoItems implements Answer<Collection<Resource>> { public static final OnlyTwoItems INSTANCE = new OnlyTwoItems(); private final List<Resource> twoItems = Arrays.asList(null, null); private final List<Resource> zeroItems = Collections.emptyList(); private int count = 0; @Override public Collection<Resource> answer(InvocationOnMock invocationOnMock) throws Throwable { if (count == 0) { count++; return twoItems; } return zeroItems; } } }