@@ -17,7 +17,6 @@ import com.datadog.android.flags.internal.model.VariationType
1717import com.datadog.android.flags.internal.repository.FlagsRepository
1818import com.datadog.android.flags.model.ErrorCode
1919import com.datadog.android.flags.model.EvaluationContext
20- import com.datadog.android.flags.model.FlagsClientState
2120import com.datadog.android.flags.model.ResolutionReason
2221import com.datadog.android.flags.utils.forge.ForgeConfigurator
2322import com.datadog.android.internal.utils.DDCoreSubscription
@@ -43,6 +42,7 @@ import org.mockito.kotlin.verify
4342import org.mockito.kotlin.verifyNoInteractions
4443import org.mockito.kotlin.whenever
4544import org.mockito.quality.Strictness
45+ import java.util.concurrent.ExecutorService
4646
4747@Extensions(
4848 ExtendWith (MockitoExtension ::class ),
@@ -70,6 +70,9 @@ internal class DatadogFlagsClientTest {
7070 @Mock
7171 lateinit var mockRumEvaluationLogger: RumEvaluationLogger
7272
73+ @Mock
74+ lateinit var mockExecutorService: ExecutorService
75+
7376 private lateinit var testedClient: DatadogFlagsClient
7477
7578 @StringForgery
@@ -83,6 +86,12 @@ internal class DatadogFlagsClientTest {
8386 whenever(mockFeatureSdkCore.internalLogger) doReturn mockInternalLogger
8487 whenever(mockFeatureSdkCore.getFeature(RUM_FEATURE_NAME )) doReturn mock()
8588
89+ // Mock executor to run tasks synchronously for testing
90+ whenever(mockExecutorService.execute(any())).thenAnswer { invocation ->
91+ val runnable = invocation.getArgument<Runnable >(0 )
92+ runnable.run ()
93+ }
94+
8695 // Mock evaluation context as ready by default
8796 // Tests that need to test "not ready" state should override this
8897 val defaultContext = EvaluationContext (
@@ -101,7 +110,10 @@ internal class DatadogFlagsClientTest {
101110 ),
102111 rumEvaluationLogger = mockRumEvaluationLogger,
103112 processor = mockProcessor,
104- flagStateChannel = FlagsStateChannel (DDCoreSubscription .create())
113+ flagStateManager = FlagsStateManager (
114+ subscription = DDCoreSubscription .create(),
115+ executorService = mockExecutorService
116+ )
105117 )
106118 }
107119
@@ -642,7 +654,11 @@ internal class DatadogFlagsClientTest {
642654 flagsRepository = customRepository,
643655 flagsConfiguration = forge.getForgery(),
644656 rumEvaluationLogger = mockRumEvaluationLogger,
645- processor = mockProcessor
657+ processor = mockProcessor,
658+ flagStateManager = FlagsStateManager (
659+ subscription = DDCoreSubscription .create(),
660+ executorService = mockExecutorService
661+ )
646662 )
647663
648664 // When
@@ -941,7 +957,11 @@ internal class DatadogFlagsClientTest {
941957 rumIntegrationEnabled = false
942958 ),
943959 rumEvaluationLogger = mockRumEvaluationLogger,
944- processor = mockProcessor
960+ processor = mockProcessor,
961+ flagStateManager = FlagsStateManager (
962+ subscription = DDCoreSubscription .create(),
963+ executorService = mockExecutorService
964+ )
945965 )
946966
947967 // When
@@ -1045,7 +1065,11 @@ internal class DatadogFlagsClientTest {
10451065 rumIntegrationEnabled = false
10461066 ),
10471067 rumEvaluationLogger = mockRumEvaluationLogger,
1048- processor = mockProcessor
1068+ processor = mockProcessor,
1069+ flagStateManager = FlagsStateManager (
1070+ subscription = DDCoreSubscription .create(),
1071+ executorService = mockExecutorService
1072+ )
10491073 )
10501074 whenever(mockFlagsRepository.getPrecomputedFlagWithContext(fakeFlagKey)) doReturn
10511075 (fakeFlag to fakeEvaluationContext)
@@ -1299,15 +1323,6 @@ internal class DatadogFlagsClientTest {
12991323
13001324 // region State Management
13011325
1302- @Test
1303- fun `M return NOT_READY W getCurrentState() {initial state}` () {
1304- // When
1305- val result = testedClient.getCurrentState()
1306-
1307- // Then
1308- assertThat(result).isEqualTo(FlagsClientState .NOT_READY )
1309- }
1310-
13111326 @Test
13121327 fun `M add listener W addStateListener()` () {
13131328 // Given
@@ -1335,64 +1350,8 @@ internal class DatadogFlagsClientTest {
13351350 verifyNoInteractions(mockListener)
13361351 }
13371352
1338- @Test
1339- fun `M notify listener W updateState() called` () {
1340- // Given
1341- val mockListener = mock(FlagsStateListener ::class .java)
1342- testedClient.addStateListener(mockListener)
1343-
1344- // When
1345- testedClient.updateState(FlagsClientState .READY , null )
1346-
1347- // Then
1348- verify(mockListener).onStateChanged(FlagsClientState .READY , null )
1349- assertThat(testedClient.getCurrentState()).isEqualTo(FlagsClientState .READY )
1350- }
1351-
1352- @Test
1353- fun `M notify listener with error W updateState(ERROR) called` () {
1354- // Given
1355- val mockListener = mock(FlagsStateListener ::class .java)
1356- val fakeError = RuntimeException (" Test error" )
1357- testedClient.addStateListener(mockListener)
1358-
1359- // When
1360- testedClient.updateState(FlagsClientState .ERROR , fakeError)
1361-
1362- // Then
1363- verify(mockListener).onStateChanged(FlagsClientState .ERROR , fakeError)
1364- assertThat(testedClient.getCurrentState()).isEqualTo(FlagsClientState .ERROR )
1365- }
1366-
1367- @Test
1368- fun `M notify all listeners W updateState() with multiple listeners` () {
1369- // Given
1370- val mockListener1 = mock(FlagsStateListener ::class .java)
1371- val mockListener2 = mock(FlagsStateListener ::class .java)
1372- testedClient.addStateListener(mockListener1)
1373- testedClient.addStateListener(mockListener2)
1374-
1375- // When
1376- testedClient.updateState(FlagsClientState .RECONCILING , null )
1377-
1378- // Then
1379- verify(mockListener1).onStateChanged(FlagsClientState .RECONCILING , null )
1380- verify(mockListener2).onStateChanged(FlagsClientState .RECONCILING , null )
1381- }
1382-
1383- @Test
1384- fun `M not notify removed listener W removeStateListener() then updateState()` () {
1385- // Given
1386- val mockListener = mock(FlagsStateListener ::class .java)
1387- testedClient.addStateListener(mockListener)
1388- testedClient.removeStateListener(mockListener)
1389-
1390- // When
1391- testedClient.updateState(FlagsClientState .READY , null )
1392-
1393- // Then
1394- verifyNoInteractions(mockListener)
1395- }
1353+ // Note: updateState() tests removed - this is now an internal method called only by
1354+ // EvaluationsManager. State notification testing is covered in FlagsStateManagerTest.
13961355
13971356 // endregion
13981357}
0 commit comments