/* * Copyright 2018-2019 Prebid.org, Inc. * * 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 org.prebid.mobile; import android.os.Bundle; import com.google.android.gms.ads.doubleclick.PublisherAdRequest; import com.mopub.mobileads.MoPubView; import org.apache.commons.lang3.reflect.FieldUtils; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.prebid.mobile.testutils.BaseSetup; import org.prebid.mobile.testutils.MockPrebidServerResponses; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowLooper; import java.util.HashSet; import okhttp3.HttpUrl; import okhttp3.mockwebserver.MockResponse; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @RunWith(RobolectricTestRunner.class) @Config(sdk = BaseSetup.testSDK) public class DemandFetcherTest extends BaseSetup { @Test public void testBaseConditions() throws Exception { PublisherAdRequest.Builder builder = new PublisherAdRequest.Builder(); PublisherAdRequest request = builder.build(); DemandFetcher demandFetcher = new DemandFetcher(request); demandFetcher.setPeriodMillis(0); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); demandFetcher.destroy(); assertEquals(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); } @Test public void testSingleRequestNoBidsResponse() throws Exception { HttpUrl httpUrl = server.url("/"); PrebidMobile.setApplicationContext(activity); Host.CUSTOM.setHostUrl(httpUrl.toString()); PrebidMobile.setPrebidServerHost(Host.CUSTOM); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.noBid())); PublisherAdRequest.Builder builder = new PublisherAdRequest.Builder(); PublisherAdRequest request = builder.build(); DemandFetcher demandFetcher = new DemandFetcher(request); PrebidMobile.setTimeoutMillis(Integer.MAX_VALUE); demandFetcher.setPeriodMillis(0); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); OnCompleteListener mockListener = mock(OnCompleteListener.class); demandFetcher.setListener(mockListener); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); ShadowLooper demandLooper = Shadows.shadowOf(demandFetcher.getDemandHandler().getLooper()); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.NO_BIDS); assertEquals(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); } @Test public void testDestroyAutoRefresh() throws Exception { HttpUrl httpUrl = server.url("/"); PrebidMobile.setApplicationContext(activity); Host.CUSTOM.setHostUrl(httpUrl.toString()); PrebidMobile.setPrebidServerHost(Host.CUSTOM); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.noBid())); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.noBid())); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.noBid())); PublisherAdRequest.Builder builder = new PublisherAdRequest.Builder(); PublisherAdRequest request = builder.build(); DemandFetcher demandFetcher = new DemandFetcher(request); PrebidMobile.setTimeoutMillis(Integer.MAX_VALUE); demandFetcher.setPeriodMillis(30); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); OnCompleteListener mockListener = mock(OnCompleteListener.class); demandFetcher.setListener(mockListener); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); ShadowLooper demandLooper = Shadows.shadowOf(demandFetcher.getDemandHandler().getLooper()); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.destroy(); assertTrue(!Robolectric.getForegroundThreadScheduler().areAnyRunnable()); assertTrue(!Robolectric.getBackgroundThreadScheduler().areAnyRunnable()); assertEquals(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); verify(mockListener, Mockito.times(1)).onComplete(ResultCode.NO_BIDS); } @Test public void testSingleRequestOneBidResponseForDFPAdObject() throws Exception { HttpUrl httpUrl = server.url("/"); PrebidMobile.setApplicationContext(activity); Host.CUSTOM.setHostUrl(httpUrl.toString()); PrebidMobile.setPrebidServerHost(Host.CUSTOM); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.oneBidFromAppNexus())); PublisherAdRequest.Builder builder = new PublisherAdRequest.Builder(); PublisherAdRequest request = builder.build(); DemandFetcher demandFetcher = new DemandFetcher(request); PrebidMobile.setTimeoutMillis(Integer.MAX_VALUE); demandFetcher.setPeriodMillis(0); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); OnCompleteListener mockListener = mock(OnCompleteListener.class); demandFetcher.setListener(mockListener); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); ShadowLooper demandLooper = Shadows.shadowOf(demandFetcher.getDemandHandler().getLooper()); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.SUCCESS); assertEquals(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); Bundle bundle = request.getCustomTargeting(); assertEquals(10, bundle.size()); assertTrue(bundle.containsKey("hb_pb")); assertEquals("0.50", bundle.get("hb_pb")); assertTrue(bundle.containsKey("hb_bidder")); assertEquals("appnexus", bundle.get("hb_bidder")); assertTrue(bundle.containsKey("hb_bidder_appnexus")); assertEquals("appnexus", bundle.get("hb_bidder_appnexus")); assertTrue(bundle.containsKey("hb_cache_id")); assertEquals("df4aba04-5e69-44b8-8608-058ab21600b8", bundle.get("hb_cache_id")); assertTrue(bundle.containsKey("hb_cache_id_appnexus")); assertEquals("df4aba04-5e69-44b8-8608-058ab21600b8", bundle.get("hb_cache_id_appnexus")); assertTrue(bundle.containsKey("hb_env")); assertEquals("mobile-app", bundle.get("hb_env")); assertTrue(bundle.containsKey("hb_env_appnexus")); assertEquals("mobile-app", bundle.get("hb_env_appnexus")); assertTrue(bundle.containsKey("hb_pb_appnexus")); assertEquals("0.50", bundle.get("hb_pb_appnexus")); assertTrue(bundle.containsKey("hb_size")); assertEquals("300x250", bundle.get("hb_size")); assertTrue(bundle.containsKey("hb_size_appnexus")); assertEquals("300x250", bundle.get("hb_size_appnexus")); } @Test public void testSingleRequestOneBidRubiconResponseForDFPAdObject() throws Exception { HttpUrl httpUrl = server.url("/"); PrebidMobile.setApplicationContext(activity); Host.CUSTOM.setHostUrl(httpUrl.toString()); PrebidMobile.setPrebidServerHost(Host.CUSTOM); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.oneBidFromRubicon())); PublisherAdRequest.Builder builder = new PublisherAdRequest.Builder(); PublisherAdRequest request = builder.build(); DemandFetcher demandFetcher = new DemandFetcher(request); PrebidMobile.setTimeoutMillis(Integer.MAX_VALUE); demandFetcher.setPeriodMillis(0); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); OnCompleteListener mockListener = mock(OnCompleteListener.class); demandFetcher.setListener(mockListener); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); ShadowLooper demandLooper = Shadows.shadowOf(demandFetcher.getDemandHandler().getLooper()); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.SUCCESS); assertEquals(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); Bundle bundle = request.getCustomTargeting(); Assert.assertEquals(16, bundle.size()); String hb_pb = "hb_pb"; Assert.assertTrue(bundle.containsKey(hb_pb)); Assert.assertEquals("1.20", bundle.get(hb_pb)); String hb_pb_rubicon = "hb_pb_rubicon"; Assert.assertTrue(bundle.containsKey(hb_pb_rubicon)); Assert.assertEquals("1.20", bundle.get(hb_pb_rubicon)); String hb_bidder = "hb_bidder"; Assert.assertTrue(bundle.containsKey(hb_bidder)); Assert.assertEquals("rubicon", bundle.get(hb_bidder)); String hb_bidder_rubicon = "hb_bidder_rubicon"; Assert.assertTrue(bundle.containsKey(hb_bidder_rubicon)); Assert.assertEquals("rubicon", bundle.get(hb_bidder_rubicon)); String hb_cache_id = "hb_cache_id"; Assert.assertTrue(bundle.containsKey(hb_cache_id)); Assert.assertEquals("a2f41588-4727-425c-9ef0-3b382debef1e", bundle.get(hb_cache_id)); String hb_cache_id_rubicon = "hb_cache_id_rubicon"; Assert.assertTrue(bundle.containsKey(hb_cache_id_rubicon)); Assert.assertEquals("a2f41588-4727-425c-9ef0-3b382debef1e", bundle.get(hb_cache_id_rubicon)); String hb_env = "hb_env"; Assert.assertTrue(bundle.containsKey(hb_env)); Assert.assertEquals("mobile-app", bundle.get(hb_env)); String hb_env_rubicon = "hb_env_rubicon"; Assert.assertTrue(bundle.containsKey(hb_env_rubicon)); Assert.assertEquals("mobile-app", bundle.get(hb_env_rubicon)); String hb_size = "hb_size"; Assert.assertTrue(bundle.containsKey(hb_size)); Assert.assertEquals("300x250", bundle.get(hb_size)); String hb_size_rubicon = "hb_size_rubicon"; Assert.assertTrue(bundle.containsKey(hb_size_rubicon)); Assert.assertEquals("300x250", bundle.get(hb_size_rubicon)); String hb_cache_hostpath = "hb_cache_hostpath"; Assert.assertTrue(bundle.containsKey(hb_cache_hostpath)); Assert.assertEquals("https://prebid-cache-europe.rubiconproject.com/cache", bundle.get(hb_cache_hostpath)); String hb_cache_hostpath_rubicon = "hb_cache_hostpath_rubicon"; Assert.assertTrue(bundle.containsKey(hb_cache_hostpath_rubicon)); Assert.assertEquals("https://prebid-cache-europe.rubiconproject.com/cache", bundle.get(hb_cache_hostpath_rubicon)); String hb_cache_path = "hb_cache_path"; Assert.assertTrue(bundle.containsKey(hb_cache_path)); Assert.assertEquals("/cache", bundle.get(hb_cache_path)); String hb_cache_path_rubicon = "hb_cache_path_rubicon"; Assert.assertTrue(bundle.containsKey(hb_cache_path_rubicon)); Assert.assertEquals("/cache", bundle.get(hb_cache_path_rubicon)); String hb_cache_host = "hb_cache_host"; Assert.assertTrue(bundle.containsKey(hb_cache_host)); Assert.assertEquals("prebid-cache-europe.rubiconproject.com", bundle.get(hb_cache_host)); String hb_cache_host_rubicon = "hb_cache_host_rubicon"; Assert.assertTrue(bundle.containsKey(hb_cache_host_rubicon)); Assert.assertEquals("prebid-cache-europe.rubiconproject.com", bundle.get(hb_cache_host_rubicon)); } @Test public void testSingleRequestOneBidResponseForMoPubAdObject() throws Exception { HttpUrl httpUrl = server.url("/"); PrebidMobile.setApplicationContext(activity); Host.CUSTOM.setHostUrl(httpUrl.toString()); PrebidMobile.setPrebidServerHost(Host.CUSTOM); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.oneBidFromAppNexus())); MoPubView adView = new MoPubView(activity); adView.setAdUnitId("123456789"); DemandFetcher demandFetcher = new DemandFetcher(adView); PrebidMobile.setTimeoutMillis(Integer.MAX_VALUE); demandFetcher.setPeriodMillis(0); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); OnCompleteListener mockListener = mock(OnCompleteListener.class); demandFetcher.setListener(mockListener); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); ShadowLooper demandLooper = Shadows.shadowOf(demandFetcher.getDemandHandler().getLooper()); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.SUCCESS); assertEquals(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); String adViewKeywords = adView.getKeywords(); assertEquals("hb_pb:0.50,hb_env:mobile-app,hb_pb_appnexus:0.50,hb_size:300x250,hb_bidder_appnexus:appnexus,hb_bidder:appnexus,hb_cache_id:df4aba04-5e69-44b8-8608-058ab21600b8,hb_env_appnexus:mobile-app,hb_size_appnexus:300x250,hb_cache_id_appnexus:df4aba04-5e69-44b8-8608-058ab21600b8,", adViewKeywords); } @Test public void testSingleRequestOneBidRubiconResponseForMoPubAdObject() throws Exception { HttpUrl httpUrl = server.url("/"); PrebidMobile.setApplicationContext(activity); Host.CUSTOM.setHostUrl(httpUrl.toString()); PrebidMobile.setPrebidServerHost(Host.CUSTOM); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.oneBidFromRubicon())); MoPubView adView = new MoPubView(activity); adView.setAdUnitId("123456789"); DemandFetcher demandFetcher = new DemandFetcher(adView); PrebidMobile.setTimeoutMillis(Integer.MAX_VALUE); demandFetcher.setPeriodMillis(0); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); OnCompleteListener mockListener = mock(OnCompleteListener.class); demandFetcher.setListener(mockListener); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); ShadowLooper demandLooper = Shadows.shadowOf(demandFetcher.getDemandHandler().getLooper()); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.SUCCESS); assertEquals(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); String adViewKeywords = adView.getKeywords(); assertEquals("hb_env:mobile-app,hb_cache_hostpath:https://prebid-cache-europe.rubiconproject.com/cache,hb_size_rubicon:300x250,hb_cache_id:a2f41588-4727-425c-9ef0-3b382debef1e,hb_cache_path_rubicon:/cache,hb_cache_host_rubicon:prebid-cache-europe.rubiconproject.com,hb_pb:1.20,hb_pb_rubicon:1.20,hb_cache_id_rubicon:a2f41588-4727-425c-9ef0-3b382debef1e,hb_cache_path:/cache,hb_size:300x250,hb_cache_hostpath_rubicon:https://prebid-cache-europe.rubiconproject.com/cache,hb_env_rubicon:mobile-app,hb_bidder:rubicon,hb_bidder_rubicon:rubicon,hb_cache_host:prebid-cache-europe.rubiconproject.com,", adViewKeywords); } @Test public void testAutoRefreshForMoPubAdObject() throws Exception { HttpUrl httpUrl = server.url("/"); PrebidMobile.setApplicationContext(activity); Host.CUSTOM.setHostUrl(httpUrl.toString()); PrebidMobile.setPrebidServerHost(Host.CUSTOM); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.oneBidFromAppNexus())); server.enqueue(new MockResponse().setResponseCode(200).setBody("{}")); MoPubView adView = new MoPubView(activity); adView.setAdUnitId("123456789"); DemandFetcher demandFetcher = new DemandFetcher(adView); PrebidMobile.setTimeoutMillis(Integer.MAX_VALUE); demandFetcher.setPeriodMillis(2000); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); OnCompleteListener mockListener = mock(OnCompleteListener.class); demandFetcher.setListener(mockListener); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); ShadowLooper demandLooper = Shadows.shadowOf(demandFetcher.getDemandHandler().getLooper()); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.SUCCESS); assertNotSame(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); String adViewKeywords = adView.getKeywords(); assertEquals("hb_pb:0.50,hb_env:mobile-app,hb_pb_appnexus:0.50,hb_size:300x250,hb_bidder_appnexus:appnexus,hb_bidder:appnexus,hb_cache_id:df4aba04-5e69-44b8-8608-058ab21600b8,hb_env_appnexus:mobile-app,hb_size_appnexus:300x250,hb_cache_id_appnexus:df4aba04-5e69-44b8-8608-058ab21600b8,", adViewKeywords); fetcherLooper.runOneTask(); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.NO_BIDS); assertNotSame(DemandFetcher.STATE.DESTROYED, FieldUtils.readField(demandFetcher, "state", true)); adViewKeywords = adView.getKeywords(); assertEquals("", adViewKeywords); } @Test public void testAutoRefreshForDFPAdObject() throws Exception { HttpUrl httpUrl = server.url("/"); PrebidMobile.setApplicationContext(activity); Host.CUSTOM.setHostUrl(httpUrl.toString()); PrebidMobile.setPrebidServerHost(Host.CUSTOM); server.enqueue(new MockResponse().setResponseCode(200).setBody(MockPrebidServerResponses.oneBidFromAppNexus())); server.enqueue(new MockResponse().setResponseCode(200).setBody("{}")); PublisherAdRequest.Builder builder = new PublisherAdRequest.Builder(); PublisherAdRequest request = builder.build(); DemandFetcher demandFetcher = new DemandFetcher(request); PrebidMobile.setTimeoutMillis(Integer.MAX_VALUE); demandFetcher.setPeriodMillis(2000); HashSet<AdSize> sizes = new HashSet<>(); sizes.add(new AdSize(300, 250)); RequestParams requestParams = new RequestParams("12345", AdType.BANNER, sizes); demandFetcher.setRequestParams(requestParams); OnCompleteListener mockListener = mock(OnCompleteListener.class); demandFetcher.setListener(mockListener); assertEquals(DemandFetcher.STATE.STOPPED, FieldUtils.readField(demandFetcher, "state", true)); demandFetcher.start(); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); ShadowLooper fetcherLooper = Shadows.shadowOf(demandFetcher.getHandler().getLooper()); fetcherLooper.runOneTask(); ShadowLooper demandLooper = Shadows.shadowOf(demandFetcher.getDemandHandler().getLooper()); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.SUCCESS); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); Bundle bundle = request.getCustomTargeting(); assertEquals(10, bundle.size()); assertTrue(bundle.containsKey("hb_pb")); assertEquals("0.50", bundle.get("hb_pb")); assertTrue(bundle.containsKey("hb_bidder")); assertEquals("appnexus", bundle.get("hb_bidder")); assertTrue(bundle.containsKey("hb_bidder_appnexus")); assertEquals("appnexus", bundle.get("hb_bidder_appnexus")); assertTrue(bundle.containsKey("hb_cache_id")); assertEquals("df4aba04-5e69-44b8-8608-058ab21600b8", bundle.get("hb_cache_id")); assertTrue(bundle.containsKey("hb_cache_id_appnexus")); assertEquals("df4aba04-5e69-44b8-8608-058ab21600b8", bundle.get("hb_cache_id_appnexus")); assertTrue(bundle.containsKey("hb_env")); assertEquals("mobile-app", bundle.get("hb_env")); assertTrue(bundle.containsKey("hb_env_appnexus")); assertEquals("mobile-app", bundle.get("hb_env_appnexus")); assertTrue(bundle.containsKey("hb_pb_appnexus")); assertEquals("0.50", bundle.get("hb_pb_appnexus")); assertTrue(bundle.containsKey("hb_size")); assertEquals("300x250", bundle.get("hb_size")); assertTrue(bundle.containsKey("hb_size_appnexus")); assertEquals("300x250", bundle.get("hb_size_appnexus")); fetcherLooper.runOneTask(); demandLooper.runOneTask(); Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); verify(mockListener).onComplete(ResultCode.NO_BIDS); assertEquals(DemandFetcher.STATE.RUNNING, FieldUtils.readField(demandFetcher, "state", true)); bundle = request.getCustomTargeting(); assertEquals(0, bundle.size()); } }