0
# Testing Support
1
2
The MyBatis Spring Boot Starter provides specialized testing support through test slice annotations that enable focused testing of MyBatis components without loading the full Spring application context.
3
4
## Capabilities
5
6
### @MybatisTest Annotation
7
8
Main test slice annotation for MyBatis-focused integration testing.
9
10
```java { .api }
11
/**
12
* Test slice annotation for MyBatis components. Loads only MyBatis-relevant
13
* configuration and uses an embedded test database by default.
14
*/
15
@Target(ElementType.TYPE)
16
@Retention(RetentionPolicy.RUNTIME)
17
@Documented
18
@Inherited
19
@BootstrapWith(MybatisTestContextBootstrapper.class)
20
@ExtendWith(SpringExtension.class)
21
@OverrideAutoConfiguration(enabled = false)
22
@TypeExcludeFilters(MybatisTypeExcludeFilter.class)
23
@Transactional
24
@AutoConfigureCache
25
@AutoConfigureMybatis
26
@AutoConfigureTestDatabase
27
@ImportAutoConfiguration
28
public @interface MybatisTest {
29
30
/**
31
* Properties to add to the Spring Environment before the test runs
32
* @return the properties to add
33
*/
34
String[] properties() default {};
35
36
/**
37
* Determines if default filtering should be used with @SpringBootApplication
38
* @return if default filters should be used
39
*/
40
boolean useDefaultFilters() default true;
41
42
/**
43
* Include filters for adding otherwise filtered beans to the application context
44
* @return include filters to apply
45
*/
46
Filter[] includeFilters() default {};
47
48
/**
49
* Exclude filters for filtering beans that would otherwise be added
50
* @return exclude filters to apply
51
*/
52
Filter[] excludeFilters() default {};
53
54
/**
55
* Auto-configuration exclusions that should be applied for this test
56
* @return auto-configuration exclusions to apply
57
*/
58
@AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
59
Class<?>[] excludeAutoConfiguration() default {};
60
}
61
```
62
63
**Usage Examples:**
64
65
```java
66
@MybatisTest
67
class UserMapperTest {
68
69
@Autowired
70
private TestEntityManager entityManager;
71
72
@Autowired
73
private UserMapper userMapper;
74
75
@Test
76
void testFindById() {
77
// Given
78
User user = new User("John", "john@example.com");
79
entityManager.persistAndFlush(user);
80
81
// When
82
User found = userMapper.findById(user.getId());
83
84
// Then
85
assertThat(found.getName()).isEqualTo("John");
86
assertThat(found.getEmail()).isEqualTo("john@example.com");
87
}
88
89
@Test
90
void testInsert() {
91
// Given
92
User user = new User("Jane", "jane@example.com");
93
94
// When
95
userMapper.insert(user);
96
97
// Then
98
assertThat(user.getId()).isNotNull();
99
User found = entityManager.find(User.class, user.getId());
100
assertThat(found.getName()).isEqualTo("Jane");
101
}
102
}
103
```
104
105
### @AutoConfigureMybatis Annotation
106
107
Lower-level annotation for including MyBatis auto-configuration in custom test slices.
108
109
```java { .api }
110
/**
111
* Auto-configuration imports for typical MyBatis tests.
112
* Most tests should use @MybatisTest instead of this annotation directly.
113
*/
114
@Target(ElementType.TYPE)
115
@Retention(RetentionPolicy.RUNTIME)
116
@Documented
117
@Inherited
118
@ImportAutoConfiguration
119
public @interface AutoConfigureMybatis {
120
// No additional attributes - provides standard MyBatis auto-configuration
121
}
122
```
123
124
**Usage Examples:**
125
126
```java
127
@DataJpaTest
128
@AutoConfigureMybatis
129
class MixedRepositoryTest {
130
131
@Autowired
132
private JpaUserRepository jpaUserRepository;
133
134
@Autowired
135
private UserMapper userMapper;
136
137
@Test
138
void testJpaAndMyBatisIntegration() {
139
// Test both JPA and MyBatis in the same test
140
User user = new User("Alice", "alice@example.com");
141
jpaUserRepository.save(user);
142
143
List<User> users = userMapper.findAll();
144
assertThat(users).hasSize(1);
145
assertThat(users.get(0).getName()).isEqualTo("Alice");
146
}
147
}
148
```
149
150
## Test Configuration Features
151
152
### Automatic Test Database Configuration
153
154
@MybatisTest automatically configures an embedded test database:
155
156
```java
157
@MybatisTest
158
class DatabaseTest {
159
// Automatically uses H2 embedded database
160
// No additional configuration required
161
}
162
163
// Override test database configuration
164
@MybatisTest
165
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.DERBY)
166
class DerbyDatabaseTest {
167
// Uses Derby instead of H2
168
}
169
170
// Use real database in tests
171
@MybatisTest
172
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
173
class RealDatabaseTest {
174
// Uses actual database configuration from application properties
175
}
176
```
177
178
### Transaction Management
179
180
Tests are automatically wrapped in transactions and rolled back:
181
182
```java
183
@MybatisTest
184
class TransactionalTest {
185
186
@Autowired
187
private UserMapper userMapper;
188
189
@Test
190
void testInsertRollback() {
191
User user = new User("Test", "test@example.com");
192
userMapper.insert(user);
193
194
// This will be rolled back after the test
195
assertThat(userMapper.findById(user.getId())).isNotNull();
196
}
197
198
@Test
199
@Commit // Override rollback behavior
200
void testInsertCommit() {
201
User user = new User("Committed", "commit@example.com");
202
userMapper.insert(user);
203
204
// This will be committed
205
}
206
}
207
```
208
209
### Custom Test Properties
210
211
Configure test-specific properties:
212
213
```java
214
@MybatisTest(properties = {
215
"mybatis.configuration.map-underscore-to-camel-case=true",
216
"mybatis.configuration.cache-enabled=false",
217
"logging.level.org.mybatis=DEBUG"
218
})
219
class CustomConfigTest {
220
// Test with custom MyBatis configuration
221
}
222
```
223
224
### Test Component Filtering
225
226
Control which components are loaded in tests:
227
228
```java
229
@MybatisTest(
230
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Service.class),
231
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)
232
)
233
class FilteredComponentTest {
234
// Includes @Service components but excludes @Controller components
235
}
236
```
237
238
## Advanced Testing Patterns
239
240
### Testing with Custom Configuration
241
242
```java
243
@MybatisTest
244
@Import(TestMyBatisConfiguration.class)
245
class CustomConfigurationTest {
246
247
@TestConfiguration
248
static class TestMyBatisConfiguration {
249
250
@Bean
251
@Primary
252
public ConfigurationCustomizer testConfigurationCustomizer() {
253
return configuration -> {
254
configuration.addInterceptor(new TestInterceptor());
255
configuration.setCallSettersOnNulls(true);
256
};
257
}
258
}
259
260
@Autowired
261
private UserMapper userMapper;
262
263
@Test
264
void testWithCustomConfiguration() {
265
// Test with custom configuration
266
}
267
}
268
```
269
270
### Mock Integration Testing
271
272
```java
273
@MybatisTest
274
class MockIntegrationTest {
275
276
@Autowired
277
private UserMapper userMapper;
278
279
@MockBean
280
private EmailService emailService;
281
282
@Test
283
void testUserCreationWithEmailService() {
284
User user = new User("John", "john@example.com");
285
userMapper.insert(user);
286
287
// Mock behavior
288
when(emailService.sendWelcomeEmail(any())).thenReturn(true);
289
290
// Test integration
291
assertThat(userMapper.findById(user.getId())).isNotNull();
292
verify(emailService, never()).sendWelcomeEmail(any()); // Just an example
293
}
294
}
295
```
296
297
### Testing Multiple Mappers
298
299
```java
300
@MybatisTest
301
class MultipleMapperTest {
302
303
@Autowired
304
private UserMapper userMapper;
305
306
@Autowired
307
private OrderMapper orderMapper;
308
309
@Test
310
void testUserOrderRelationship() {
311
// Create user
312
User user = new User("John", "john@example.com");
313
userMapper.insert(user);
314
315
// Create order for user
316
Order order = new Order(user.getId(), "Product A", 99.99);
317
orderMapper.insert(order);
318
319
// Test relationship
320
List<Order> userOrders = orderMapper.findByUserId(user.getId());
321
assertThat(userOrders).hasSize(1);
322
assertThat(userOrders.get(0).getProduct()).isEqualTo("Product A");
323
}
324
}
325
```
326
327
### Performance Testing
328
329
```java
330
@MybatisTest(properties = {
331
"mybatis.configuration.cache-enabled=true",
332
"logging.level.org.mybatis=TRACE"
333
})
334
class PerformanceTest {
335
336
@Autowired
337
private UserMapper userMapper;
338
339
@Test
340
void testBatchInsert() {
341
List<User> users = IntStream.range(0, 1000)
342
.mapToObj(i -> new User("User" + i, "user" + i + "@example.com"))
343
.collect(Collectors.toList());
344
345
StopWatch stopWatch = new StopWatch();
346
stopWatch.start();
347
348
users.forEach(userMapper::insert);
349
350
stopWatch.stop();
351
352
assertThat(stopWatch.getTotalTimeMillis()).isLessThan(5000);
353
assertThat(userMapper.count()).isEqualTo(1000);
354
}
355
}
356
```