/* * Copyright 2016 Google Inc. All rights reserved. * * 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.google.samples.apps.iosched.myschedule; import android.content.Context; import android.content.SharedPreferences; import android.test.suitebuilder.annotation.SmallTest; import com.google.samples.apps.iosched.Config; import com.google.samples.apps.iosched.archframework.Model; import com.google.samples.apps.iosched.model.ScheduleHelper; import com.google.samples.apps.iosched.model.ScheduleItem; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import java.util.ArrayList; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @SmallTest public class MyScheduleModelTest { private static final long FAKE_CURRENT_TIME_OFFSET = 0l; private static final String FAKE_TITLE_1 = "FAKE TITLE 1"; private static final String FAKE_TITLE_2 = "FAKE TITLE 2"; @Mock private Context mMockContext; @Mock private SharedPreferences mMockSharedPreferences; @Mock private ScheduleHelper mMockScheduleHelper; @Mock private ArrayList<ScheduleItem> mMockScheduleItems; @Mock private Model.DataQueryCallback mMockDataQueryCallback; @Mock private Model.UserActionCallback mMockUserActionCallback; @Mock private ScheduleItem mMockScheduleItem1; @Mock private ScheduleItem mMockScheduleItem2; @Captor private ArgumentCaptor<MyScheduleModel.LoadScheduleDataListener> mLoadScheduleDataCallbackCaptor; private MyScheduleModel mMyScheduleModel; @Before public void setUp() { // Init mocks initSharedPreferencesMock(); initMockContextWithFakeCurrentTime(); // Create an instance of the model. mMyScheduleModel = spy(new MyScheduleModel(mMockScheduleHelper, mMockContext)); } @Test public void scheduleQuery_scheduleHelperCalled_dataUpdatedAndCallbackFired() { // Given mock schedule items setUpMockScheduleItems(); int conferenceDays = Config.CONFERENCE_DAYS.length; // When requesting a data update mMyScheduleModel.requestData(MyScheduleModel.MyScheduleQueryEnum.SCHEDULE, mMockDataQueryCallback); // Then the schedule helper is called for each day verify(mMockScheduleHelper, times(conferenceDays)).getScheduleDataAsync( mLoadScheduleDataCallbackCaptor.capture(), anyLong(), anyLong()); // Given the schedule helper returning the same mock schedule items for each day mLoadScheduleDataCallbackCaptor.getValue().onDataLoaded(mMockScheduleItems); // Then the model is updated with the mock schedule items for the last conference day // and callback is fired verify(mMyScheduleModel).updateCache(conferenceDays, mMockScheduleItems, mMockDataQueryCallback); assertThat(mMyScheduleModel.getConferenceDataForDay(conferenceDays).size(), is(2)); assertThat(mMyScheduleModel.getConferenceDataForDay(conferenceDays).get(0).getTitle(), is(FAKE_TITLE_1)); assertThat(mMyScheduleModel.getConferenceDataForDay(conferenceDays).get(1).getTitle(), is(FAKE_TITLE_2)); verify(mMockDataQueryCallback).onModelUpdated(mMyScheduleModel, MyScheduleModel.MyScheduleQueryEnum.SCHEDULE); } @Test public void reloadDataUserAction_scheduleHelperCalled_dataUpdatedAndCallbackFired() { // Given mock schedule items setUpMockScheduleItems(); int conferenceDays = Config.CONFERENCE_DAYS.length; // When delivering user action to reload the data mMyScheduleModel.deliverUserAction(MyScheduleModel.MyScheduleUserActionEnum.RELOAD_DATA, null, mMockUserActionCallback); // Then the schedule helper is called for each day verify(mMockScheduleHelper, times(conferenceDays)).getScheduleDataAsync( mLoadScheduleDataCallbackCaptor.capture(), anyLong(), anyLong()); // Given the schedule helper returning the same mock schedule items for each day mLoadScheduleDataCallbackCaptor.getValue().onDataLoaded(mMockScheduleItems); // Then the model is updated with the mock schedule items for the last conference day // and callback is fired verify(mMyScheduleModel).updateCache(eq(conferenceDays), eq(mMockScheduleItems), any(Model.DataQueryCallback.class)); assertThat(mMyScheduleModel.getConferenceDataForDay(conferenceDays).size(), is(2)); assertThat(mMyScheduleModel.getConferenceDataForDay(conferenceDays).get(0).getTitle(), is(FAKE_TITLE_1)); assertThat(mMyScheduleModel.getConferenceDataForDay(conferenceDays).get(1).getTitle(), is(FAKE_TITLE_2)); verify(mMockUserActionCallback).onModelUpdated(mMyScheduleModel, MyScheduleModel.MyScheduleUserActionEnum.RELOAD_DATA); } @Test public void redrawUIUserAction_scheduleHelperNotCalled_CallbackFired() { // When delivering user action to redraw the UI mMyScheduleModel .deliverUserAction(MyScheduleModel.MyScheduleUserActionEnum.REDRAW_UI, null, mMockUserActionCallback); // Then the schedule helper is not called verify(mMockScheduleHelper, never()).getScheduleDataAsync( mLoadScheduleDataCallbackCaptor.capture(), anyLong(), anyLong()); // Then the callback is fired verify(mMockUserActionCallback).onModelUpdated(mMyScheduleModel, MyScheduleModel.MyScheduleUserActionEnum.REDRAW_UI); } private void initSharedPreferencesMock() { when(mMockContext.getPackageName()).thenReturn("mock_name"); when(mMockContext.getSharedPreferences("mock_name_preferences", Context.MODE_PRIVATE)) .thenReturn(mMockSharedPreferences); } private void initMockContextWithFakeCurrentTime() { when(mMockSharedPreferences.getLong("mock_current_time", eq(anyLong()))) .thenReturn(FAKE_CURRENT_TIME_OFFSET); } private void setUpMockScheduleItems() { when(mMockScheduleItems.size()).thenReturn(2); when(mMockScheduleItems.get(0)).thenReturn(mMockScheduleItem1); when(mMockScheduleItems.get(1)).thenReturn(mMockScheduleItem2); when(mMockScheduleItem1.getTitle()).thenReturn(FAKE_TITLE_1); when(mMockScheduleItem2.getTitle()).thenReturn(FAKE_TITLE_2); } }