Skip to content

Commit 0723cc1

Browse files
committed
fix: moved tests as Instrumentation Tests
1 parent 7d1e926 commit 0723cc1

File tree

4 files changed

+210
-133
lines changed

4 files changed

+210
-133
lines changed

maps-app/build.gradle.kts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ android {
6161
imageDifferenceThreshold = 0.035f // 3.5%
6262
}
6363
}
64+
65+
packaging {
66+
resources {
67+
pickFirsts += listOf(
68+
"META-INF/LICENSE.md",
69+
"META-INF/LICENSE-notice.md"
70+
)
71+
}
72+
}
6473
}
6574

6675
dependencies {
@@ -90,6 +99,8 @@ dependencies {
9099
androidTestImplementation(libs.androidx.test.compose.ui)
91100
androidTestImplementation(libs.kotlinx.coroutines.test)
92101
androidTestImplementation(libs.truth)
102+
androidTestImplementation(libs.mockk.android)
103+
//androidTestImplementation(kotlin("test"))
93104

94105
testImplementation(libs.test.junit)
95106
testImplementation(libs.robolectric)

maps-app/src/androidTest/java/com/google/maps/android/compose/internal/GoogleMapsInitializerTest.kt

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ import org.junit.After
2626
import org.junit.Test
2727
import org.junit.runner.RunWith
2828
import kotlin.time.Duration.Companion.milliseconds
29+
import com.google.android.gms.common.ConnectionResult
30+
import com.google.android.gms.common.GooglePlayServicesMissingManifestValueException
31+
import com.google.android.gms.maps.MapsInitializer
32+
import com.google.android.gms.maps.MapsApiSettings
33+
import io.mockk.coEvery
34+
import io.mockk.coVerify
35+
import io.mockk.mockkStatic
36+
import io.mockk.Runs
37+
import io.mockk.just
2938

3039
@OptIn(ExperimentalCoroutinesApi::class)
3140
@RunWith(AndroidJUnit4::class)
@@ -119,4 +128,108 @@ class GoogleMapsInitializerTest {
119128

120129
assertThat(googleMapsInitializer.state.value).isEqualTo(InitializationState.UNINITIALIZED)
121130
}
131+
132+
@Test
133+
fun testInitializeSuccessState() = runTest {
134+
// Arrange
135+
mockkStatic(MapsInitializer::class)
136+
assertThat(googleMapsInitializer.state.value).isEqualTo(InitializationState.UNINITIALIZED)
137+
138+
coEvery { MapsInitializer.initialize(any()) } returns ConnectionResult.SUCCESS
139+
140+
val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
141+
// Act
142+
// Direct call pattern matching original successful test structure
143+
googleMapsInitializer.initialize(context)
144+
145+
// Assert
146+
assertThat(googleMapsInitializer.state.value).isEqualTo(InitializationState.SUCCESS)
147+
coVerify(exactly = 1) { MapsInitializer.initialize(
148+
eq(context),
149+
any(),
150+
any(),
151+
)}
152+
}
153+
154+
@Test
155+
fun testInitializeConcurrentCallsOnlyRunOnce() = runTest {
156+
mockkStatic(MapsInitializer::class)
157+
coEvery { MapsInitializer.initialize(any()) } returns ConnectionResult.SUCCESS
158+
159+
val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
160+
val job1 = launch { googleMapsInitializer.initialize(context) }
161+
val job2 = launch { googleMapsInitializer.initialize(context) }
162+
163+
job1.join()
164+
job2.join()
165+
166+
// Assert: The actual initialization method should only have been called once
167+
coVerify(exactly = 1) { MapsInitializer.initialize(
168+
eq(context),
169+
any(),
170+
any(),
171+
)}
172+
assertThat(googleMapsInitializer.state.value).isEqualTo(InitializationState.SUCCESS)
173+
}
174+
175+
@Test
176+
fun testInitializeUnrecoverableFailureSetsFailureState() = runTest {
177+
// Arrange
178+
mockkStatic(MapsInitializer::class)
179+
val error = GooglePlayServicesMissingManifestValueException()
180+
181+
val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
182+
var caughtException: Throwable? = null
183+
184+
coEvery {
185+
MapsInitializer.initialize(
186+
eq(context),
187+
isNull(),
188+
any()
189+
)
190+
} throws error
191+
192+
// Act
193+
val job = launch {
194+
try {
195+
googleMapsInitializer.initialize(context)
196+
} catch (e: GooglePlayServicesMissingManifestValueException) {
197+
caughtException = e
198+
}
199+
}
200+
job.join()
201+
202+
// Assert: The exception was caught, and the state became FAILURE
203+
assertThat(caughtException).isInstanceOf(GooglePlayServicesMissingManifestValueException::class.java)
204+
assertThat(caughtException).isEqualTo(error)
205+
206+
// 2. Assert the state was set to FAILURE
207+
assertThat(googleMapsInitializer.state.value).isEqualTo(InitializationState.FAILURE)
208+
}
209+
210+
@Test
211+
fun testInitializeSuccessAlsoSetsAttributionId() = runTest {
212+
// Arrange: Mock MapsApiSettings locally
213+
mockkStatic(MapsInitializer::class, MapsApiSettings::class)
214+
215+
coEvery { MapsInitializer.initialize(any()) } returns ConnectionResult.SUCCESS
216+
coEvery { MapsApiSettings.addInternalUsageAttributionId(any(), any()) } just Runs
217+
218+
val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
219+
220+
// Act
221+
// Direct call pattern matching original successful test structure
222+
googleMapsInitializer.initialize(context)
223+
224+
// Assert: Verify both the primary initialization and the attribution call occurred
225+
coVerify(exactly = 1) {
226+
MapsInitializer.initialize(
227+
eq(context),
228+
any(),
229+
any(),
230+
)
231+
}
232+
coVerify(exactly = 1) { MapsApiSettings.addInternalUsageAttributionId(any(), any()) }
233+
assertThat(googleMapsInitializer.state.value).isEqualTo(InitializationState.SUCCESS)
234+
}
122235
}
Lines changed: 86 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
2-
<!--
1+
<?xml version="1.0" encoding="utf-8"?><!--
32
Copyright 2023 Google LLC
43
54
Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,96 +16,96 @@
1716

1817
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
1918

20-
<uses-permission android:name="android.permission.INTERNET" />
19+
<uses-permission android:name="android.permission.INTERNET" />
2120

22-
<application
23-
android:name=".MapsComposeApplication"
24-
android:allowBackup="true"
25-
android:icon="@mipmap/ic_launcher"
26-
android:label="@string/app_name"
27-
android:roundIcon="@mipmap/ic_launcher_round"
28-
android:supportsRtl="true"
29-
android:theme="@style/Theme.AndroidMapsCompose" >
21+
<application
22+
android:name=".MapsComposeApplication"
23+
android:allowBackup="true"
24+
android:icon="@mipmap/ic_launcher"
25+
android:label="@string/app_name"
26+
android:roundIcon="@mipmap/ic_launcher_round"
27+
android:supportsRtl="true"
28+
android:theme="@style/Theme.AndroidMapsCompose">
3029

31-
<meta-data
32-
android:name="com.google.android.geo.API_KEY"
33-
android:value="${MAPS_API_KEY}" />
30+
<meta-data
31+
android:name="com.google.android.geo.API_KEY"
32+
android:value="${MAPS_API_KEY}" />
3433

35-
<activity
36-
android:name=".MainActivity"
37-
android:exported="true">
38-
<intent-filter>
39-
<action android:name="android.intent.action.MAIN" />
40-
<category android:name="android.intent.category.LAUNCHER" />
41-
</intent-filter>
42-
</activity>
34+
<activity
35+
android:name=".MainActivity"
36+
android:exported="true">
37+
<intent-filter>
38+
<action android:name="android.intent.action.MAIN" />
39+
<category android:name="android.intent.category.LAUNCHER" />
40+
</intent-filter>
41+
</activity>
4342

44-
<!--
45-
All activities in this sample are exported. This is for demonstration
46-
purposes, to make it easy to launch each sample activity directly.
43+
<!--
44+
All activities in this sample are exported. This is for demonstration
45+
purposes, to make it easy to launch each sample activity directly.
4746
48-
In a real-world application, you should carefully consider which activities
49-
to export. In most cases, only the main launcher activity should be exported.
50-
Exporting an activity means that any other app on the device can launch it.
51-
-->
52-
53-
<activity
54-
android:name=".BasicMapActivity"
55-
android:exported="true" />
56-
<activity
57-
android:name=".markerexamples.AdvancedMarkersActivity"
58-
android:exported="true"/>
59-
<activity
60-
android:name=".MapInColumnActivity"
61-
android:exported="true"/>
62-
<activity
63-
android:name=".MapsInLazyColumnActivity"
64-
android:exported="true"/>
65-
<activity
66-
android:name=".markerexamples.MarkerClusteringActivity"
67-
android:exported="true"/>
68-
<activity
69-
android:name=".LocationTrackingActivity"
70-
android:exported="true"/>
71-
<activity
72-
android:name=".ScaleBarActivity"
73-
android:exported="true"/>
74-
<activity
75-
android:name=".StreetViewActivity"
76-
android:exported="true"/>
77-
<activity
78-
android:name=".CustomControlsActivity"
79-
android:exported="true"/>
80-
<activity
81-
android:name=".AccessibilityActivity"
82-
android:exported="true"/>
83-
<activity
84-
android:name=".RecompositionActivity"
85-
android:exported="true"/>
86-
<activity
87-
android:name=".FragmentDemoActivity"
88-
android:exported="true"/>
89-
<activity
90-
android:name=".markerexamples.markerdragevents.MarkerDragEventsActivity"
91-
android:exported="true"/>
92-
<activity
93-
android:name=".markerexamples.markerscollection.MarkersCollectionActivity"
94-
android:exported="true"/>
95-
<activity
96-
android:name=".markerexamples.syncingdraggablemarkerwithdatamodel.SyncingDraggableMarkerWithDataModelActivity"
97-
android:exported="true"/>
98-
<activity
99-
android:name=".markerexamples.updatingnodragmarkerwithdatamodel.UpdatingNoDragMarkerWithDataModelActivity"
100-
android:exported="true"/>
101-
<activity
102-
android:name=".markerexamples.draggablemarkerscollectionwithpolygon.DraggableMarkersCollectionWithPolygonActivity"
103-
android:exported="true"/>
104-
<activity
105-
android:name=".TileOverlayActivity"
106-
android:exported="true"/>
47+
In a real-world application, you should carefully consider which activities
48+
to export. In most cases, only the main launcher activity should be exported.
49+
Exporting an activity means that any other app on the device can launch it.
50+
-->
10751

108-
<!-- Used by createComponentActivity() for unit testing -->
109-
<activity android:name="androidx.activity.ComponentActivity" />
52+
<activity
53+
android:name=".BasicMapActivity"
54+
android:exported="true" />
55+
<activity
56+
android:name=".markerexamples.AdvancedMarkersActivity"
57+
android:exported="true" />
58+
<activity
59+
android:name=".MapInColumnActivity"
60+
android:exported="true" />
61+
<activity
62+
android:name=".MapsInLazyColumnActivity"
63+
android:exported="true" />
64+
<activity
65+
android:name=".markerexamples.MarkerClusteringActivity"
66+
android:exported="true" />
67+
<activity
68+
android:name=".LocationTrackingActivity"
69+
android:exported="true" />
70+
<activity
71+
android:name=".ScaleBarActivity"
72+
android:exported="true" />
73+
<activity
74+
android:name=".StreetViewActivity"
75+
android:exported="true" />
76+
<activity
77+
android:name=".CustomControlsActivity"
78+
android:exported="true" />
79+
<activity
80+
android:name=".AccessibilityActivity"
81+
android:exported="true" />
82+
<activity
83+
android:name=".RecompositionActivity"
84+
android:exported="true" />
85+
<activity
86+
android:name=".FragmentDemoActivity"
87+
android:exported="true" />
88+
<activity
89+
android:name=".markerexamples.markerdragevents.MarkerDragEventsActivity"
90+
android:exported="true" />
91+
<activity
92+
android:name=".markerexamples.markerscollection.MarkersCollectionActivity"
93+
android:exported="true" />
94+
<activity
95+
android:name=".markerexamples.syncingdraggablemarkerwithdatamodel.SyncingDraggableMarkerWithDataModelActivity"
96+
android:exported="true" />
97+
<activity
98+
android:name=".markerexamples.updatingnodragmarkerwithdatamodel.UpdatingNoDragMarkerWithDataModelActivity"
99+
android:exported="true" />
100+
<activity
101+
android:name=".markerexamples.draggablemarkerscollectionwithpolygon.DraggableMarkersCollectionWithPolygonActivity"
102+
android:exported="true" />
103+
<activity
104+
android:name=".TileOverlayActivity"
105+
android:exported="true" />
110106

111-
</application>
107+
<!-- Used by createComponentActivity() for unit testing -->
108+
<activity android:name="androidx.activity.ComponentActivity" />
109+
110+
</application>
112111
</manifest>

0 commit comments

Comments
 (0)