基于spring-boot的应用程序的单元+集成测试方案 (4)

@MybatisTest搜索配置类的逻辑和@SpringBootTest、@WebMvcTest相同,为了避免Spring环境问题(上文在测试Controller一节中介绍过),这里直接使用内部类进行配置。

@FixMethodOrder(MethodSorters.NAME_ASCENDING)用来指定测试方法的执行顺序,这是为了观察事务回滚的效果。

如果将test1_insert方法上的@Rollback(false)注释放开,事务不会回滚,test2_doNothing方法之后打印输出的内容会包含test1_insert方法里插入的数据。

反之,如果注释掉,事务回滚,test2_doNothing方法之后打印输出的内容不包含test1_insert方法里插入的数据。

使用外部数据库

首先,添加对应的数据库驱动依赖,以及数据源配置。比如使用mysql外部数据库:

<!-- pom.xml --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-jdbc.version}</version> </dependency> # application.yml spring: datasource: url: jdbc:mysql://localhost:3306/test?autoReconnect=true&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&useSSL=false username: root password: root driver-class-name: com.mysql.jdbc.Driver

然后配置测试类,唯一不同的是,在测试类上要多加一个@AutoConfigureTestDatabase注解:

@RunWith(SpringRunner.class) @MybatisTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class CityMapperTest2 { @SpringBootApplication(scanBasePackages = {"com.shouzheng.demo.mapper"}) static class InnerConfig {} @Autowired private CityMapper cityMapper; // ... }

这样,测试的时候就会使用我们配置的数据库进行测试,而不是使用内存数据库。

事务回滚设置

测试持久层时,默认是回滚的。可以在具体的测试方法上添加@Rollback(false)来禁止回滚,也可以在测试类上添加。

集成测试

集成测试时会超脱一个类的范围,我们需要保证自测试目标类及以下的依赖类,都能够在spring容器中被实例化,最简单的方式莫过于构建完整的spring上下文。虽然这样一来,会有很多和测试目标无关的类也会被实例化,但是我们省去了精心设计初始化bean的工夫,而且也间接的达到了“测试构建完整的spring上下文”的目的。

从Controller开始测试

例如我们以上文中介绍到的controller为测试目标,测试newCity请求。测试类如下:

@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoTestSpringBootApplication.class) @AutoConfigureMockMvc @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class CityControllerWithRollbackTest { private static Logger LOG = LoggerFactory.getLogger(CityControllerWithRollbackTest.class); @Autowired private MockMvc mockMvc; @Before @After public void getAllCities() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/cities")) .andDo(result -> { String content = result.getResponse().getContentAsString(); LOG.info("cities = {}", content); }); } @Test @Transactional // @Rollback(false) public void test1_insertCity() throws Exception { LOG.info("insert a city"); mockMvc.perform(MockMvcRequestBuilders.post("/city") .contentType(MediaType.APPLICATION_JSON) .content("{\"name\": \"杭州\", \"state\": \"浙江\", \"country\": \"中国\"}")) .andExpect(MockMvcResultMatchers.status().isOk()); } /** * 为了观察数据库是否回滚 */ @Test public void test2_doNothind() { } }

这段代码主要测试新增数据记录的请求,并在测试前后分别请求并打印当前的数据记录集。我们可以看到,在test1_insertCity方法运行之后打印的数据集,会比在此之前打印的数据集多一条记录,而这条记录正是我们申请新增的数据记录。

test2_doNothind是一个辅助的测试方法,在完成test1_insertCity方法之后,开始执行test2_doNothind测试。而测试前的打印数据记录集的行为,可以让我们观察到test1_insertCity测试中新增的数据是否发生回滚。

集成测试时使用@SpringBootTest注解,指定配置类为项目启动类。如果我们的项目是基于spring-cloud的微服务环境,那么也可以使用内部配置类来减少服务注册等相关的配置。

@AutoConfigureMockMvc是为了实例化MockMvc实例,用来发送http请求。

事务回滚设置

实验证明,集成测试依然可以支持数据库操作回滚,方案就是在测试方法上使用@Transactional注解,标识事务性操作。同时,我们依然可以使用@Rollback来设置是否回滚。

从中间层开始测试

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdfwd.html