pringContextTests {
@Autowired
private FooService foo;
@Test
public void testPlusCount() throws Exception {
assertEquals(foo.getCount(), 0);
foo.plusCount();
assertEquals(foo.getCount(), 1);
}
}
避免@SpringBootConfiguration冲突
当@SpringBootTest没有定义(classes=…,且没有找到nested @Configuration class的情况下,会尝试查询@SpringBootConfiguration,如果找到多个的话则会抛出异常:
Caused by: java.lang.IllegalStateException: Found multiple @SpringBootConfiguration annotated classes [Generic bean: class [...]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [/Users/qianjia/workspace-os/spring-test-examples/basic/target/test-classes/me/chanjar/basic/springboot/ex7/FooServiceImplTest1.class], Generic bean: class [me.chanjar.basic.springboot.ex7.FooServiceImplTest2]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [...]]
比如以下代码就会造成这个问题:
@SpringBootApplication(scanBasePackages = "me.chanjar.basic.service")
public class Config1 {
}
@SpringBootApplication(scanBasePackages = "me.chanjar.basic.service")
public class Config2 {
}
@SpringBootTest
public class FooServiceImplTest extends AbstractTestNGSpringContextTests {
// ...
}
解决这个问题的方法有就是避免自动查询@SpringBootConfiguration:
- 定义@SpringBootTest(classes=…)
- 提供nested @Configuration class
最佳实践
除了单元测试(不需要初始化ApplicationContext的测试)外,尽量将测试配置和生产配置保持一致。比如如果生产配置里启用了AutoConfiguration,那么测试配置也应该启用。因为只有这样才能够在测试环境下发现生产环境的问题,也避免出现一些因为配置不同导致的奇怪问题。
在测试代码之间尽量做到配置共用,这么做的优点有3个:
- 能够有效利用Spring TestContext Framework的缓存机制,ApplicationContext只会创建一次,后面的测试会直接用已创建的那个,加快测试代码运行速度。
- 当项目中的Bean很多的时候,这么做能够降低测试代码复杂度,想想如果每个测试代码都有一套自己的@Configuration或其变体,那得多吓人。
参考文档