0
# Type and Null Assertions
1
2
Assertions for type checking and null safety validation, essential for ensuring type safety and handling nullable values in Kotlin tests.
3
4
## Capabilities
5
6
### Type Assertions
7
8
#### assertIs Function
9
10
Asserts that a value is of a specific type and performs a smart cast.
11
12
```kotlin { .api }
13
/**
14
* Asserts that value is of type T and returns it cast to T
15
* @param value - Value to check and cast
16
* @param message - Optional custom failure message
17
* @return The value cast to type T
18
*/
19
inline fun <reified T> assertIs(value: Any?, message: String? = null): T
20
```
21
22
**Usage Examples:**
23
24
```kotlin
25
import kotlin.test.*
26
27
@Test
28
fun testTypeChecking() {
29
val obj: Any = "hello world"
30
31
// Assert type and get typed reference
32
val str = assertIs<String>(obj)
33
assertEquals(11, str.length)
34
35
// With custom message
36
val number: Any = 42
37
val int = assertIs<Int>(number, "Value should be an integer")
38
assertTrue(int > 0)
39
40
// Works with nullable types
41
val nullableValue: Any? = "test"
42
val result = assertIs<String>(nullableValue)
43
assertEquals("test", result)
44
}
45
46
@Test
47
fun testPolymorphism() {
48
val shapes: List<Any> = listOf(
49
Circle(5.0),
50
Rectangle(10.0, 20.0),
51
"not a shape"
52
)
53
54
shapes.forEach { shape ->
55
when {
56
shape is Circle -> {
57
val circle = assertIs<Circle>(shape)
58
assertTrue(circle.radius > 0)
59
}
60
shape is Rectangle -> {
61
val rect = assertIs<Rectangle>(shape)
62
assertTrue(rect.width > 0 && rect.height > 0)
63
}
64
}
65
}
66
}
67
```
68
69
#### assertIsNot Function
70
71
Asserts that a value is not of a specific type.
72
73
```kotlin { .api }
74
/**
75
* Asserts that value is not of type T
76
* @param value - Value to check
77
* @param message - Optional custom failure message
78
*/
79
inline fun <reified T> assertIsNot(value: Any?, message: String? = null)
80
```
81
82
**Usage Examples:**
83
84
```kotlin
85
@Test
86
fun testTypeRejection() {
87
val obj: Any = 42
88
89
// Assert it's not a string
90
assertIsNot<String>(obj)
91
assertIsNot<List<*>>(obj, "Should not be a list")
92
93
// Test with null
94
val nullValue: Any? = null
95
assertIsNot<String>(nullValue, "Null should not be considered a String")
96
}
97
98
@Test
99
fun testInputValidation() {
100
fun processInput(input: Any) {
101
assertIsNot<Collection<*>>(input, "Input should not be a collection")
102
// Safe to process as non-collection
103
}
104
105
processInput("string")
106
processInput(42)
107
processInput(true)
108
}
109
```
110
111
### Null Assertions
112
113
#### assertNotNull Function
114
115
Asserts that a value is not null and returns it as a non-null type.
116
117
```kotlin { .api }
118
/**
119
* Asserts that the actual value is not null
120
* @param actual - Nullable value to check
121
* @param message - Optional custom failure message
122
* @return The value cast to non-null type T
123
*/
124
fun <T : Any> assertNotNull(actual: T?, message: String? = null): T
125
126
/**
127
* Asserts that the actual value is not null and processes it with a block
128
* @param actual - Nullable value to check
129
* @param message - Optional custom failure message
130
* @param block - Function to execute with the non-null value
131
*/
132
inline fun <T : Any, R> assertNotNull(actual: T?, message: String? = null, block: (T) -> R)
133
```
134
135
**Usage Examples:**
136
137
```kotlin
138
@Test
139
fun testNotNullValues() {
140
val name: String? = getName()
141
142
// Assert not null and get non-null reference
143
val safeName = assertNotNull(name, "Name should not be null")
144
assertTrue(safeName.isNotEmpty())
145
146
// Using the block form
147
val user: User? = findUser("john")
148
assertNotNull(user, "User should be found") { u ->
149
assertEquals("john", u.username)
150
assertTrue(u.isActive)
151
}
152
}
153
154
@Test
155
fun testDatabaseResults() {
156
val connection: DatabaseConnection? = getConnection()
157
assertNotNull(connection, "Database connection should be established")
158
159
val result: QueryResult? = connection.executeQuery("SELECT * FROM users")
160
assertNotNull(result, "Query should return results") { queryResult ->
161
assertTrue(queryResult.hasRows())
162
assertNotNull(queryResult.getFirstRow())
163
}
164
}
165
166
@Test
167
fun testNullableChaining() {
168
val data: String? = loadData()
169
170
// Chain operations after null check
171
assertNotNull(data) { safeData ->
172
val processed = safeData.uppercase().trim()
173
assertTrue(processed.isNotEmpty())
174
assertEquals("EXPECTED", processed)
175
}
176
}
177
```
178
179
#### assertNull Function
180
181
Asserts that a value is null.
182
183
```kotlin { .api }
184
/**
185
* Asserts that the actual value is null
186
* @param actual - Value to check for nullness
187
* @param message - Optional custom failure message
188
*/
189
fun assertNull(actual: Any?, message: String? = null)
190
```
191
192
**Usage Examples:**
193
194
```kotlin
195
@Test
196
fun testNullValues() {
197
val emptyResult: String? = findNonExistentItem()
198
assertNull(emptyResult, "Should return null for non-existent item")
199
200
// Test cleanup
201
var resource: Resource? = createResource()
202
resource.close()
203
resource = null
204
assertNull(resource, "Resource should be null after cleanup")
205
}
206
207
@Test
208
fun testOptionalOperations() {
209
val cache = mutableMapOf<String, String>()
210
211
// Key doesn't exist
212
val missing = cache["nonexistent"]
213
assertNull(missing, "Non-existent key should return null")
214
215
// After removal
216
cache["key"] = "value"
217
cache.remove("key")
218
assertNull(cache["key"], "Removed key should return null")
219
}
220
221
@Test
222
fun testNullableTypes() {
223
fun maybeProcess(input: String?): String? {
224
return if (input?.isNotEmpty() == true) input.uppercase() else null
225
}
226
227
// Test null input
228
assertNull(maybeProcess(null))
229
assertNull(maybeProcess(""))
230
231
// Test valid input
232
val result = maybeProcess("hello")
233
assertNotNull(result)
234
assertEquals("HELLO", result)
235
}
236
```
237
238
## Advanced Usage Patterns
239
240
### Type-Safe Testing with Generics
241
242
```kotlin
243
@Test
244
fun testGenericTypes() {
245
val list: Any = listOf("a", "b", "c")
246
247
// Assert specific generic type
248
val stringList = assertIs<List<*>>(list)
249
assertEquals(3, stringList.size)
250
251
// More specific assertion
252
val strings = assertIs<List<String>>(list)
253
assertTrue(strings.all { it is String })
254
}
255
```
256
257
### Nullable Reference Chains
258
259
```kotlin
260
@Test
261
fun testNullableChains() {
262
data class User(val profile: Profile?)
263
data class Profile(val email: String?)
264
265
val user: User? = getUser()
266
assertNotNull(user, "User should exist") { u ->
267
assertNotNull(u.profile, "User should have profile") { profile ->
268
assertNotNull(profile.email, "Profile should have email") { email ->
269
assertTrue(email.contains("@"))
270
}
271
}
272
}
273
}
274
```
275
276
### Error Handling with Type Checks
277
278
```kotlin
279
@Test
280
fun testErrorHandling() {
281
val response: Any = makeApiCall()
282
283
when {
284
response is ErrorResponse -> {
285
val error = assertIs<ErrorResponse>(response)
286
assertTrue(error.code > 0)
287
assertNotNull(error.message)
288
}
289
response is SuccessResponse -> {
290
val success = assertIs<SuccessResponse>(response)
291
assertNotNull(success.data)
292
}
293
else -> {
294
fail("Unexpected response type: ${response::class}")
295
}
296
}
297
}
298
```
299
300
### Combining Type and Null Assertions
301
302
```kotlin
303
@Test
304
fun testCombinedAssertions() {
305
val result: Any? = processInput("test")
306
307
// First check it's not null
308
assertNotNull(result, "Processing should return a value")
309
310
// Then check its type
311
val stringResult = assertIs<String>(result, "Result should be a string")
312
313
// Finally verify content
314
assertTrue(stringResult.isNotEmpty())
315
assertEquals("PROCESSED: test", stringResult)
316
}
317
```