From b8dbc68ff41c8d99ceff442405603dcab706fa49 Mon Sep 17 00:00:00 2001 From: Mihai-Cristian Condrea Date: Tue, 16 Sep 2025 21:22:55 +0300 Subject: [PATCH] Ensure AdUtils initialization guards against null context --- .../androidtutorials/java/ads/AdUtils.java | 6 ++- .../java/ads/AdUtilsTest.java | 43 +++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ads/AdUtils.java b/app/src/main/java/com/d4rk/androidtutorials/java/ads/AdUtils.java index 23acf6cc..403e6b48 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ads/AdUtils.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ads/AdUtils.java @@ -8,6 +8,8 @@ import com.google.android.gms.ads.AdView; import com.google.android.gms.ads.MobileAds; +import java.util.Objects; + public final class AdUtils { private static boolean initialized = false; @@ -17,7 +19,9 @@ private AdUtils() { public static synchronized void initialize(Context context) { if (!initialized) { - MobileAds.initialize(context.getApplicationContext()); + Context nonNullContext = Objects.requireNonNull(context, "context == null"); + Context appContext = nonNullContext.getApplicationContext(); + MobileAds.initialize(appContext != null ? appContext : nonNullContext); initialized = true; } } diff --git a/app/src/test/java/com/d4rk/androidtutorials/java/ads/AdUtilsTest.java b/app/src/test/java/com/d4rk/androidtutorials/java/ads/AdUtilsTest.java index 4ccde6a3..d268cee4 100644 --- a/app/src/test/java/com/d4rk/androidtutorials/java/ads/AdUtilsTest.java +++ b/app/src/test/java/com/d4rk/androidtutorials/java/ads/AdUtilsTest.java @@ -1,5 +1,8 @@ package com.d4rk.androidtutorials.java.ads; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; import android.content.Context; @@ -21,16 +24,32 @@ */ public class AdUtilsTest { + private Field initializedField; + @Before public void setUp() throws Exception { // Reset the initialized flag before each test - Field field = AdUtils.class.getDeclaredField("initialized"); - field.setAccessible(true); - field.set(null, false); + initializedField = AdUtils.class.getDeclaredField("initialized"); + initializedField.setAccessible(true); + initializedField.set(null, false); } @Test - public void initialize_callsMobileAdsInitializeOnlyOnce() { + public void initialize_firstCallInitializesAdsAndSetsFlag() throws Exception { + Context context = mock(Context.class); + when(context.getApplicationContext()).thenReturn(context); + + try (MockedStatic mobileAds = mockStatic(MobileAds.class)) { + AdUtils.initialize(context); + + mobileAds.verify(() -> MobileAds.initialize(context), times(1)); + } + + assertTrue(isInitialized()); + } + + @Test + public void initialize_subsequentCallsDoNothing() throws Exception { Context context = mock(Context.class); when(context.getApplicationContext()).thenReturn(context); @@ -40,6 +59,18 @@ public void initialize_callsMobileAdsInitializeOnlyOnce() { mobileAds.verify(() -> MobileAds.initialize(context), times(1)); } + + assertTrue(isInitialized()); + } + + @Test + public void initialize_withNullContext_throwsNullPointerException() throws Exception { + try (MockedStatic mobileAds = mockStatic(MobileAds.class)) { + assertThrows(NullPointerException.class, () -> AdUtils.initialize(null)); + mobileAds.verifyNoInteractions(); + } + + assertFalse(isInitialized()); } @Test @@ -84,4 +115,8 @@ public void loadBanner_withOtherView_doesNothing() { mobileAds.verifyNoInteractions(); } } + + private boolean isInitialized() throws IllegalAccessException { + return initializedField.getBoolean(null); + } }