@@ -20,14 +20,17 @@ import com.klaviyo.core.networking.NetworkMonitor
20
20
import com.klaviyo.core.networking.NetworkObserver
21
21
import com.klaviyo.fixtures.BaseTest
22
22
import io.mockk.every
23
+ import io.mockk.just
23
24
import io.mockk.mockk
24
25
import io.mockk.mockkConstructor
25
26
import io.mockk.mockkObject
27
+ import io.mockk.runs
26
28
import io.mockk.slot
27
29
import io.mockk.spyk
28
30
import io.mockk.unmockkConstructor
29
31
import io.mockk.unmockkObject
30
32
import io.mockk.verify
33
+ import java.net.HttpURLConnection
31
34
import java.net.URL
32
35
import kotlinx.coroutines.Dispatchers
33
36
import kotlinx.coroutines.launch
@@ -39,6 +42,7 @@ import org.junit.Assert.assertEquals
39
42
import org.junit.Assert.assertNotEquals
40
43
import org.junit.Assert.assertNotNull
41
44
import org.junit.Assert.assertNull
45
+ import org.junit.Assert.fail
42
46
import org.junit.Before
43
47
import org.junit.Test
44
48
@@ -564,7 +568,8 @@ internal class KlaviyoApiClientTest : BaseTest() {
564
568
565
569
@Test
566
570
fun `Rate limited requests are retried with backoff until max attempts in absence of Retry-After header` () {
567
- val defaultInterval = Registry .config.networkFlushIntervals[NetworkMonitor .NetworkType .Wifi .position]
571
+ val defaultInterval =
572
+ Registry .config.networkFlushIntervals[NetworkMonitor .NetworkType .Wifi .position]
568
573
569
574
// First unsent request, which we will retry till max attempts
570
575
val request1 = mockRequest(" uuid-retry" , KlaviyoApiRequest .Status .Unsent ).also {
@@ -712,4 +717,43 @@ internal class KlaviyoApiClientTest : BaseTest() {
712
717
assertEquals(" [\" mock_uuid2\" ]" , actualQueue) // Expect queue to reflect the dropped item
713
718
assertNull(spyDataStore.fetch(" mock_uuid1" )) // Expect the item to be cleared from store
714
719
}
720
+
721
+ @Test
722
+ fun `response body handles null stream correctly` () {
723
+ // Create a KlaviyoApiRequest with required arguments
724
+ val request = KlaviyoApiRequest (" mockPath" , RequestMethod .GET )
725
+
726
+ // Spy on that specific instance
727
+ val spiedRequest = spyk(request)
728
+
729
+ // Mock network connection and config
730
+ every { Registry .networkMonitor.isNetworkConnected() } returns true
731
+ // Mock URL and URLConnection
732
+ val urlMock = mockk<URL >()
733
+ val connectionMock = mockk<HttpURLConnection >()
734
+
735
+ // Set up mocks for URL and connection
736
+ every { urlMock.openConnection() } returns connectionMock
737
+ every { urlMock.protocol } returns " http"
738
+ every { connectionMock.inputStream } returns null
739
+ every { connectionMock.errorStream } returns null
740
+ every { connectionMock.responseCode } returns HttpURLConnection .HTTP_INTERNAL_ERROR
741
+ every { connectionMock.headerFields } returns emptyMap()
742
+ every { connectionMock.setRequestProperty(any(), any()) } returns Unit
743
+ every { connectionMock.requestMethod = any() } returns Unit
744
+ every { connectionMock.readTimeout = any() } returns Unit
745
+ every { connectionMock.connectTimeout = any() } returns Unit
746
+ every { connectionMock.disconnect() } just runs
747
+ every { connectionMock.connect() } just runs
748
+
749
+ // Mock the URL used by the request to our mocked URL
750
+ every { spiedRequest.url } returns urlMock
751
+
752
+ try {
753
+ // Attempt to send without an exception occurring
754
+ spiedRequest.send()
755
+ } catch (e: NullPointerException ) {
756
+ fail(" NullPointerException was thrown: ${e.message} " )
757
+ }
758
+ }
715
759
}
0 commit comments