0
# Test Assumptions
1
2
The Assume object provides methods for conditional test execution. When assumptions fail, tests are skipped rather than failing, making them ideal for tests that depend on specific environmental conditions or prerequisites.
3
4
## Core Assumption Methods
5
6
### Boolean Assumptions
7
8
```scala { .api }
9
object Assume {
10
def assumeTrue(b: Boolean): Unit
11
def assumeTrue(message: String, b: Boolean): Unit
12
def assumeFalse(b: Boolean): Unit
13
def assumeFalse(message: String, b: Boolean): Unit
14
}
15
```
16
17
**Usage:**
18
```scala
19
import org.junit.Assume._
20
21
class EnvironmentDependentTest {
22
@Test
23
def shouldRunOnLinux(): Unit = {
24
assumeTrue("Test only runs on Linux", System.getProperty("os.name").contains("Linux"))
25
26
// This test only runs if we're on Linux
27
val result = linuxSpecificOperation()
28
assertNotNull(result)
29
}
30
31
@Test
32
def shouldSkipInCI(): Unit = {
33
assumeFalse("Skip in CI environment", System.getenv("CI") != null)
34
35
// This test is skipped in CI environments
36
performSlowLocalTest()
37
}
38
}
39
```
40
41
### Null Assumptions
42
43
```scala { .api }
44
def assumeNotNull(objects: AnyRef*): Unit
45
```
46
47
**Usage:**
48
```scala
49
@Test
50
def shouldWorkWithExternalService(): Unit = {
51
val apiKey = System.getenv("API_KEY")
52
val serviceUrl = System.getenv("SERVICE_URL")
53
54
assumeNotNull("External service configuration required", apiKey, serviceUrl)
55
56
// Test only runs if both environment variables are set
57
val client = new ExternalServiceClient(apiKey, serviceUrl)
58
val response = client.ping()
59
assertEquals("OK", response.getStatus())
60
}
61
```
62
63
### Hamcrest Matcher Assumptions
64
65
```scala { .api }
66
def assumeThat[T](actual: T, matcher: Matcher[T]): Unit
67
def assumeThat[T](message: String, actual: T, matcher: Matcher[T]): Unit
68
```
69
70
**Usage:**
71
```scala
72
import org.hamcrest.CoreMatchers._
73
74
@Test
75
def shouldRunWithSufficientMemory(): Unit = {
76
val runtime = Runtime.getRuntime
77
val maxMemory = runtime.maxHeapSize()
78
79
assumeThat("Need at least 1GB heap", maxMemory, is(greaterThan(1024 * 1024 * 1024L)))
80
81
// Test only runs with sufficient memory
82
performMemoryIntensiveOperation()
83
}
84
85
@Test
86
def shouldWorkWithSpecificJavaVersion(): Unit = {
87
val javaVersion = System.getProperty("java.version")
88
89
assumeThat("Java 11+ required", javaVersion, not(startsWith("1.8")))
90
91
// Test skipped on Java 8
92
useJava11Features()
93
}
94
```
95
96
### Exception Assumptions
97
98
```scala { .api }
99
def assumeNoException(e: Throwable): Unit
100
def assumeNoException(message: String, e: Throwable): Unit
101
```
102
103
**Usage:**
104
```scala
105
@Test
106
def shouldConnectToDatabase(): Unit = {
107
var connection: Connection = null
108
var connectionError: Throwable = null
109
110
try {
111
connection = DriverManager.getConnection(databaseUrl)
112
} catch {
113
case e: SQLException => connectionError = e
114
}
115
116
assumeNoException("Database must be available", connectionError)
117
118
// Test only runs if database connection succeeded
119
val result = connection.createStatement().executeQuery("SELECT 1")
120
assertTrue(result.next())
121
}
122
```
123
124
## Assumption vs Assertion Behavior
125
126
### Assumptions - Skip Tests
127
```scala
128
@Test
129
def assumptionExample(): Unit = {
130
assumeTrue(false) // Test is SKIPPED
131
fail("This is never reached")
132
}
133
```
134
135
### Assertions - Fail Tests
136
```scala
137
@Test
138
def assertionExample(): Unit = {
139
assertTrue(false) // Test FAILS
140
fail("This is never reached")
141
}
142
```
143
144
## Common Use Cases
145
146
### Platform-Specific Tests
147
148
```scala
149
class PlatformSpecificTest {
150
@Test
151
def shouldRunOnWindows(): Unit = {
152
assumeTrue(System.getProperty("os.name").toLowerCase().contains("windows"))
153
// Windows-specific test logic
154
}
155
156
@Test
157
def shouldRunOnUnix(): Unit = {
158
val os = System.getProperty("os.name").toLowerCase()
159
assumeTrue(os.contains("linux") || os.contains("mac"))
160
// Unix-specific test logic
161
}
162
}
163
```
164
165
### Environment Configuration Tests
166
167
```scala
168
class ConfigurationTest {
169
@Test
170
def shouldTestWithRedisEnabled(): Unit = {
171
assumeTrue("Redis integration tests",
172
System.getProperty("test.redis.enabled", "false").toBoolean)
173
174
val redis = new RedisClient()
175
redis.set("key", "value")
176
assertEquals("value", redis.get("key"))
177
}
178
179
@Test
180
def shouldTestProductionConfig(): Unit = {
181
assumeThat("Production profile required",
182
System.getProperty("spring.profiles.active"), is("production"))
183
184
// Test production-specific configuration
185
}
186
}
187
```
188
189
### Resource Availability Tests
190
191
```scala
192
class ResourceDependentTest {
193
@Test
194
def shouldTestWithExternalService(): Unit = {
195
var serviceAvailable = false
196
try {
197
val socket = new Socket("external-service.com", 80)
198
socket.close()
199
serviceAvailable = true
200
} catch {
201
case _: IOException => // Service not available
202
}
203
204
assumeTrue("External service must be reachable", serviceAvailable)
205
206
// Test external service integration
207
val client = new ExternalServiceClient()
208
val response = client.getData()
209
assertNotNull(response)
210
}
211
}
212
```
213
214
### Java Version Compatibility
215
216
```scala
217
class VersionCompatibilityTest {
218
@Test
219
def shouldUseJava11Features(): Unit = {
220
val version = System.getProperty("java.version")
221
assumeThat("Java 11+ required for this test",
222
version, not(anyOf(startsWith("1.6"), startsWith("1.7"), startsWith("1.8"))))
223
224
// Use Java 11+ features
225
val result = List.of("a", "b", "c") // Java 9+ List.of
226
assertEquals(3, result.size())
227
}
228
}
229
```
230
231
## Exception Handling
232
233
When assumptions fail, they throw `AssumptionViolatedException`:
234
235
```scala { .api }
236
class AssumptionViolatedException(message: String) extends RuntimeException
237
```
238
239
This exception is caught by the test runner and causes the test to be marked as "skipped" rather than "failed".
240
241
**Internal Implementation:**
242
```scala
243
// When assumption fails
244
if (!condition) {
245
throw new AssumptionViolatedException(message)
246
}
247
```
248
249
## Integration with Test Runners
250
251
Test runners handle assumption violations specially:
252
253
- **JUnit Runner**: Reports test as "ignored" or "skipped"
254
- **IDE Integration**: Shows skipped tests with different visual indicator
255
- **Build Tools**: Count skipped tests separately from passed/failed
256
- **CI/CD**: Skipped tests don't cause build failures
257
258
## Best Practices
259
260
1. **Use for Environmental Dependencies**: Skip tests when external resources aren't available
261
2. **Provide Clear Messages**: Always include descriptive messages explaining why tests are skipped
262
3. **Document Assumptions**: Make test requirements clear in test names and documentation
263
4. **Avoid Overuse**: Don't use assumptions to hide poorly written tests
264
5. **Consider Test Categories**: Use JUnit categories or tags as alternative to assumptions
265
6. **Validate Early**: Put assumptions at the beginning of test methods
266
267
## Assumptions vs Test Categories
268
269
**Assumptions** (runtime checking):
270
```scala
271
@Test
272
def shouldTestSlowOperation(): Unit = {
273
assumeTrue("Slow tests enabled", System.getProperty("test.slow", "false").toBoolean)
274
performSlowOperation()
275
}
276
```
277
278
**Categories** (compile-time filtering):
279
```scala
280
@Category(Array(classOf[SlowTests]))
281
@Test
282
def shouldTestSlowOperation(): Unit = {
283
performSlowOperation()
284
}
285
```
286
287
Use assumptions when the decision to skip depends on runtime conditions. Use categories when the decision can be made at build time.