SpringBoot单元测试实践
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@Transactional
@Rollback(true)
public class HelloServiceTest {
@Autowired
private HelloService helloService;
@Test
public void sayHello() {
helloService.sayHello("zhangsan");
// XXX Asset
}
@SpringBootTest
启动了SpringBoot环境,classes = Application.class
则扫描了该类下的所有的Bean@Transactional
含有数据库操作,需要增加该注解@Rollback(true)
数据库事务默认回滚,用来保障数据隔离
使用内存数据库 h2 + flayway为dao层测试
mock feign client
Feign Client接口:
@FeignClient(value = "baidu")
public interface BaiduApi {
@GetMapping("index.html")
String index();
}
上层业务逻辑:
@Component
public class BaiduManager {
@Resource
private BaiduApi baiduApi;
public String getIndex() {
return baiduApi.index();
}
}
单元测试:
@SpringBootTest
class BaiduManagerTest {
@Resource
private BaiduManager baiduManager;
// `@MockBean`会生成一个Mock对象,并取代已存在的相同类型的单例bean,如果不存在则添加
@MockBean(name = "com.tenmao.utdemo.BaiduApi")
private BaiduApi baiduApi;
@Test
void getIndex() {
Mockito.when(baiduApi.index()).thenReturn("baidu index");
String index = baiduManager.getIndex();
Assertions.assertEquals("baidu index", index);
}
}
注意:
Mock对象并没有取代实际对象:
@MockBean(name = "com.tenmao.utdemo.BaiduApi")
需要设置name为全限定符
@SpringBootTest 性能优化
webEnvironment
这个属性决定了测试类要不要启动一个 web 环境,说白了就是要不要启动一个 Tomcat 容器,可选的值为:MOCK, 启动一个模拟的 Servlet 环境,这是默认值
RANDOM_PORT,启动一个 Tomcat 容器,并监听一个随机的端口号
DEFINED_PORT,启动一个 Tomcat 容器,并监听配置文件中定义的端口(未定义则默认监听8080)
NONE,不启动 Tomcat 容器。只需要通过指定
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
即可达到加速的效果。这时测试类启动时就只会初始化 Spring 上下文,不再启动 Tomcat 容器了!
classes
属性,用来指定运行测试类需要装载的 class 集合,如果不指定,那么会默认装载@SpringBootConfiguration
注解标注的类。如果我们不指定classes属性,那么启动测试类时需要加载的Bean的数量和正常启动一次入口类(即有@SpringBootApplication
注解的类)加载的 Bean 数量是一样的。特别是含有
@PostConstruct
注解指定的Bean以及实现了CommandLineRunner
接口的Bean,他们可能会有很长的初始化时间。启动时,如果选择只加载需要的Bean上下文,就可以加快速度。
使用
@ComponentScan
来指明Spring 扫描Bean的范围,也可以缩小Bean所扫描的范围@ContextConfiguration
定义类级元数据,用于确定如何为集成测试加载和配置,简单的说就是通过该注解定义Spring容器在启动是需要加载的上下文(配置类、配置文件、实例化的Bean),可以用于最小化测试,提升测试效率。
最后更新于
这有帮助吗?