1
+ package com.jetbrains.spacetutorial
2
+
3
+ import app.cash.sqldelight.db.SqlDriver
4
+ import com.jetbrains.spacetutorial.cache.Database
5
+ import com.jetbrains.spacetutorial.cache.DatabaseDriverFactory
6
+ import com.jetbrains.spacetutorial.entity.Links
7
+ import com.jetbrains.spacetutorial.entity.Patch
8
+ import com.jetbrains.spacetutorial.entity.RocketLaunch
9
+ import com.jetbrains.spacetutorial.network.SpaceXApi
10
+ import io.mockk.coEvery
11
+ import io.mockk.every
12
+ import io.mockk.mockk
13
+ import kotlinx.coroutines.test.runTest
14
+ import org.junit.Before
15
+ import org.junit.Test
16
+ import kotlin.test.assertEquals
17
+ import kotlin.test.assertFailsWith
18
+
19
+ /* *
20
+ * Android-specific unit tests for the SpaceXSDK class.
21
+ */
22
+ class SpaceXSDKTest {
23
+
24
+ // Mock dependencies
25
+ private val mockApi = mockk<SpaceXApi >()
26
+ private val mockDatabaseDriverFactory = mockk<DatabaseDriverFactory >()
27
+ private val mockSqlDriver = mockk<SqlDriver >()
28
+
29
+ // Create the SDK instance with mock dependencies
30
+ private lateinit var sdk: SpaceXSDK
31
+
32
+ // Sample data for testing
33
+ private val sampleLaunches = listOf (
34
+ RocketLaunch (
35
+ flightNumber = 1 ,
36
+ missionName = " Test Mission 1" ,
37
+ launchDateUTC = " 2023-01-01T12:00:00Z" ,
38
+ details = " Test details 1" ,
39
+ launchSuccess = true ,
40
+ links = Links (
41
+ patch = Patch (
42
+ small = " small_url_1" ,
43
+ large = " large_url_1"
44
+ ),
45
+ article = " article_url_1"
46
+ )
47
+ ),
48
+ RocketLaunch (
49
+ flightNumber = 2 ,
50
+ missionName = " Test Mission 2" ,
51
+ launchDateUTC = " 2023-02-01T12:00:00Z" ,
52
+ details = " Test details 2" ,
53
+ launchSuccess = false ,
54
+ links = Links (
55
+ patch = Patch (
56
+ small = " small_url_2" ,
57
+ large = " large_url_2"
58
+ ),
59
+ article = " article_url_2"
60
+ )
61
+ )
62
+ )
63
+
64
+ private val sampleLaunches2 = listOf (
65
+ RocketLaunch (
66
+ flightNumber = 3 ,
67
+ missionName = " Test Mission 3" ,
68
+ launchDateUTC = " 2023-01-01T12:00:00Z" ,
69
+ details = " Test details 3" ,
70
+ launchSuccess = true ,
71
+ links = Links (
72
+ patch = Patch (
73
+ small = " small_url_3" ,
74
+ large = " large_url_3"
75
+ ),
76
+ article = " article_url_3"
77
+ )
78
+ ),
79
+ )
80
+
81
+ // Cache for storing launches in tests
82
+ private val launchesCache = mutableListOf<RocketLaunch >()
83
+
84
+ @Before
85
+ fun setup () {
86
+ // Clear the cache before each test
87
+ launchesCache.clear()
88
+
89
+ // Setup the mock database driver factory
90
+ every { mockDatabaseDriverFactory.createDriver() } returns mockSqlDriver
91
+
92
+ // Create a new SDK instance for each test with mocked dependencies
93
+ sdk = SpaceXSDK (mockDatabaseDriverFactory, mockApi)
94
+ }
95
+
96
+ /* *
97
+ * Test that getLaunches returns cached data when available and forceReload is false.
98
+ */
99
+ @Test
100
+ fun testGetLaunchesFromCache () = runTest {
101
+ // Setup: Mock the database to return cached launches
102
+ val databaseField = SpaceXSDK ::class .java.getDeclaredField(" database" )
103
+ databaseField.isAccessible = true
104
+ val mockDatabase = mockk<Database >()
105
+ databaseField.set(sdk, mockDatabase)
106
+
107
+ // Mock the getAllLaunches method of the Database class
108
+ every { mockDatabase.getAllLaunches() } returns sampleLaunches
109
+
110
+ // Act: Call getLaunches with forceReload = false
111
+ val result = sdk.getLaunches(forceReload = false )
112
+
113
+ // Assert: The result should be the cached launches
114
+ assertEquals(sampleLaunches, result)
115
+ }
116
+
117
+ /* *
118
+ * Test that getLaunches fetches data from the API when cache is empty.
119
+ */
120
+ @Test
121
+ fun testGetLaunchesFromApiWhenCacheEmpty () = runTest {
122
+ // Setup: Mock the database to return empty list and the API to return sample launches
123
+ val databaseField = SpaceXSDK ::class .java.getDeclaredField(" database" )
124
+ databaseField.isAccessible = true
125
+ val mockDatabase = mockk<Database >()
126
+ databaseField.set(sdk, mockDatabase)
127
+
128
+ // Mock the getAllLaunches method of the Database class to return an empty list
129
+ every { mockDatabase.getAllLaunches() } returns emptyList()
130
+
131
+ // Mock the clearAndCreateLaunches method of the Database class
132
+ every { mockDatabase.clearAndCreateLaunches(any()) } returns Unit
133
+
134
+ // Mock the API to return sample launches
135
+ coEvery { mockApi.getAllLaunches() } returns sampleLaunches
136
+
137
+ // Act: Call getLaunches with forceReload = false (but cache is empty)
138
+ val result = sdk.getLaunches(forceReload = false )
139
+
140
+ // Assert: The result should be the launches from the API
141
+ assertEquals(sampleLaunches, result)
142
+ }
143
+
144
+ /* *
145
+ * Test that getLaunches fetches data from the API when forceReload is true.
146
+ */
147
+ @Test
148
+ fun testGetLaunchesWithForceReload () = runTest {
149
+ // Setup: Mock the database and API
150
+ val databaseField = SpaceXSDK ::class .java.getDeclaredField(" database" )
151
+ databaseField.isAccessible = true
152
+ val mockDatabase = mockk<Database >()
153
+ databaseField.set(sdk, mockDatabase)
154
+
155
+ // Mock the getAllLaunches method of the Database class to return cached launches
156
+ every { mockDatabase.getAllLaunches() } returns sampleLaunches
157
+
158
+ // Mock the clearAndCreateLaunches method of the Database class
159
+ every { mockDatabase.clearAndCreateLaunches(any()) } returns Unit
160
+
161
+ // Mock the API to return sample launches
162
+ coEvery { mockApi.getAllLaunches() } returns sampleLaunches2
163
+
164
+ // Act: Call getLaunches with forceReload = true
165
+ val result = sdk.getLaunches(forceReload = true )
166
+
167
+ // Assert: The result should be the launches from the API
168
+ assertEquals(sampleLaunches2, result)
169
+ }
170
+
171
+ /* *
172
+ * Test that getLaunches throws an exception when the API call fails.
173
+ */
174
+ @Test
175
+ fun testGetLaunchesException () = runTest {
176
+ // Setup: Mock the database and API
177
+ val databaseField = SpaceXSDK ::class .java.getDeclaredField(" database" )
178
+ databaseField.isAccessible = true
179
+ val mockDatabase = mockk<Database >()
180
+ databaseField.set(sdk, mockDatabase)
181
+
182
+ // Mock the getAllLaunches method of the Database class to return an empty list
183
+ every { mockDatabase.getAllLaunches() } returns emptyList()
184
+
185
+ // Mock the API to throw an exception
186
+ coEvery { mockApi.getAllLaunches() } throws Exception (" API error" )
187
+
188
+ // Act & Assert: Call getLaunches should throw an exception
189
+ val exception = assertFailsWith<Exception > {
190
+ sdk.getLaunches(forceReload = true )
191
+ }
192
+
193
+ // Verify the exception message
194
+ assertEquals(" API error" , exception.message)
195
+ }
196
+ }
0 commit comments