1.环境准备
Spring-boot官方给我们提供了测试用的场景启动器:spring-boot-starter-test
如果我们用IDEA创建一个spring项目,默认会给我们在pom里面引入这个依赖。其实有这个依赖就已经够了,因为它已经帮我们内置了Mock测试的核心mockito,也会帮我们引入junit,我这里的boot版本是2.5.7,junit用的5,所以后续都是在这个基础上做演示。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.关于Mock
项目部署前都需要先跑一遍test,一可以确认环境没问题,二可以保证业务代码能在我们预期内。所以写好测试代码很重要,很多开源项目的test都是特别优秀的模板,大家有空可以去学习学习。
mock就是模拟,模拟的目的是为了让我们专注于某一个方法的内部逻辑是否如我们预期,至于它内部又调用了其他方法应该返回什么,我们不关心,因为每一个方法都应该有对应的测试用例去覆盖,我们mock的就是跟它自身业务无关的一系列操作。
假如我们现在测试controller层的业务逻辑(其实controller层也没啥逻辑,常见的就是参数校验),controller内会注入service,如果我们只专注于controller的逻辑,就需要mock一个servcie实例去代替我们完成它内部的调用,从而让controller的业务逻辑排除service的干扰,即使service层洪水滔天,只要我们controller安然无恙就好,后面自会有service对应的测试方法去排查。
这样的好处是显而易见的:如果我们仅仅为了验证controller层的参数校验逻辑是不是对的,就要让service去执行它的逻辑,再调用数据访问层,假如sql写错了,我们就得花精力去改。而我们的初衷仅仅是想验证一下参数校验是不是写对了,走了太多弯路,非常难受。其次假如我们是一次update或者delete,测试完之后就得回滚,复杂场景下,transaction也帮不了我们,何况还有跟多不支持事务的数据库。除此还有很多延伸问题,这些问题有了mokito框架都可以帮我们解决。
3.实战
直接上代码
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.Random.class)
class CollectsResourceTest {