package com.mopub.nativeads; import android.app.Activity; import com.mopub.common.test.support.SdkTestRunner; import com.mopub.common.util.test.support.ShadowAsyncTasks; import com.mopub.common.util.test.support.TestMethodBuilderFactory; import com.mopub.nativeads.MoPubNative.MoPubNativeEventListener; import com.mopub.nativeads.MoPubNative.MoPubNativeNetworkListener; import com.mopub.network.MoPubNetworkError; import com.mopub.network.Networking; import com.mopub.volley.Request; import com.mopub.volley.RequestQueue; import com.mopub.volley.VolleyError; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; import java.net.MalformedURLException; import java.util.concurrent.Semaphore; import static android.Manifest.permission.ACCESS_NETWORK_STATE; import static android.Manifest.permission.INTERNET; import static com.mopub.common.VolleyRequestMatcher.isUrl; import static com.mopub.common.util.Reflection.MethodBuilder; import static com.mopub.nativeads.MoPubNative.EMPTY_EVENT_LISTENER; import static com.mopub.nativeads.MoPubNative.EMPTY_NETWORK_LISTENER; import static org.fest.assertions.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.Robolectric.shadowOf; @RunWith(SdkTestRunner.class) @Config(shadows = {ShadowAsyncTasks.class}) public class MoPubNativeTest { private MoPubNative subject; private MethodBuilder methodBuilder; private Activity context; private Semaphore semaphore; private static final String adUnitId = "test_adunit_id"; @Mock private MoPubNativeEventListener mockEventListener; @Mock private MoPubNativeNetworkListener mockNetworkListener; @Mock private RequestQueue mockRequestQueue; @Before public void setup() { context = new Activity(); shadowOf(context).grantPermissions(ACCESS_NETWORK_STATE); shadowOf(context).grantPermissions(INTERNET); subject = new MoPubNative(context, adUnitId, mockNetworkListener); methodBuilder = TestMethodBuilderFactory.getSingletonMock(); Networking.setRequestQueueForTesting(mockRequestQueue); semaphore = new Semaphore(0); } @After public void tearDown() { reset(methodBuilder); } @Test public void destroy_shouldSetListenersToEmptyAndClearContext() { assertThat(subject.getContextOrDestroy()).isSameAs(context); assertThat(subject.getMoPubNativeNetworkListener()).isSameAs(mockNetworkListener); subject.setNativeEventListener(mockEventListener); assertThat(subject.getMoPubNativeEventListener()).isSameAs(mockEventListener); subject.destroy(); assertThat(subject.getContextOrDestroy()).isNull(); assertThat(subject.getMoPubNativeNetworkListener()).isSameAs(EMPTY_NETWORK_LISTENER); assertThat(subject.getMoPubNativeEventListener()).isSameAs(EMPTY_EVENT_LISTENER); } @Test public void setNativeEventListener_shouldSetListener() { assertThat(subject.getMoPubNativeNetworkListener()).isSameAs(mockNetworkListener); subject.setNativeEventListener(mockEventListener); assertThat(subject.getMoPubNativeEventListener()).isSameAs(mockEventListener); subject.setNativeEventListener(null); assertThat(subject.getMoPubNativeEventListener()).isSameAs(EMPTY_EVENT_LISTENER); } @Test public void loadNativeAd_shouldReturnFast() { Robolectric.getUiThreadScheduler().pause(); subject.destroy(); subject.makeRequest(); assertThat(Robolectric.getUiThreadScheduler().enqueuedTaskCount()).isEqualTo(0); } @Test public void requestNativeAd_shouldFireNetworkRequest() { subject.requestNativeAd("http://www.mopub.com"); verify(mockNetworkListener, never()).onNativeFail(any(NativeErrorCode.class)); verify(mockRequestQueue).add(argThat(isUrl("http://www.mopub.com"))); } @Test public void requestNativeAd_whenReqeustQueueDeliversUnknownError_shouldFireNativeFail() { when(mockRequestQueue.add(any(Request.class))) .then(new Answer<Void>() { @Override public Void answer(final InvocationOnMock invocationOnMock) throws Throwable { ((Request) invocationOnMock.getArguments()[0]).deliverError(new VolleyError(new MalformedURLException())); return null; } }); subject.requestNativeAd("//\\//\\::::"); verify(mockNetworkListener).onNativeFail(any(NativeErrorCode.class)); } @Test public void requestNativeAd_withNullUrl_shouldFireNativeFail() { Robolectric.getUiThreadScheduler().pause(); subject.requestNativeAd(null); verify(mockNetworkListener).onNativeFail(any(NativeErrorCode.class)); verify(mockRequestQueue, never()).add(any(Request.class)); } @Test public void onAdError_shouldNotifyListener() { subject.onAdError(new MoPubNetworkError(MoPubNetworkError.Reason.BAD_BODY)); verify(mockNetworkListener).onNativeFail(eq(NativeErrorCode.INVALID_JSON)); } @Test public void onAdError_whenNotMoPubError_shouldNotifyListener() { subject.onAdError(new VolleyError("generic")); verify(mockNetworkListener).onNativeFail(eq(NativeErrorCode.UNSPECIFIED)); } }