SpringBoot 单元测试
Spring Boot中的单元测试与Spring中的测试一脉相承,但是又做了大量的简化,只需要少量的代码就能搭建一个测试环境,进而实现对Controller、Service或者Dao层的代码进行测试。
基本用法:
创建一个Spring Boot项目时,创建成功后,默认都添加了spring-boot-starter-test依赖,并且创建好了测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class XcSpringbootApplicationTests {
@Test
public void contextLoads() {
}
}
- @RunWith注解,该注解将JUnit执行类修改为SpringRunner,而SpringRunner是Spring Framework中测试类SpringJUnit4ClassRunner的别名。
- @Spring BootTest注解除了提供Spring TestContext中的常规测试功能之外,还提供了其他特性:提供默认的ContextLoader、自动搜索@SpringBootConfiguration、自定义环境属性、为不同的webEnvironment模式提供支持,这里的webEnvironment模式主要有4种:
- MOCK,这种模式是当classpath下存在servletAPIS时,就会创建WebApplicationContext并提供一个mockservlet环境;当classpath下存在Spring WebFlux时,则创建ReactiveWebApplicationContext;若都不存在,则创建一个常规的ApplicationContext。
- RANDOM_PORT,这种模式将提供一个真实的Servlet环境,使用内嵌的容器,但是端口随机。
- DEFINED_PORT,这种模式也将提供一个真实的Servlet环境,使用内嵌的容器,但是使用定义好的端口。
- NONE,这种模式则加载一个普通的ApplicationContext,不提供任何Servlet环境。这种一般不适用于Web测试。
- 在Spring测试中,开发者一般使用@ContextConfiguration(classes = )或者@ContextConfiguration(locations = )来指定要加载的Spring配置,而在Spring Boot中则不需要这么麻烦,Spring Boot中的@*Test注解将会去包含测试类的包下查找带有@Spring BootApplication或者@SpringBootConfiguration注解的主配置类。
- @Test注解则来自junit,junit中的@After、@AfterClass、@Before、@BeforeClass、@Ignore等注解一样可以在这里使用。
Service测试:
Service层的测试就是常规测试,,例如现在有一个HelloService
需要对HelloService进行测试,直接在测试类中注入HelloService即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @RunWith (SpringRunner. class ) @SpringBootTest public class HelloServiceTest { @Autowired HelloServiceImpl helloService; @Test public void contextLoads() { String hello = helloService.sayHello( "Michael" ); Assert.assertThat(hello, Matchers.is( "Hello Michael !" )); } } |
在测试类中注入HelloService,然后调用相关方法即可。使用Assert判断测试结果是否正确。
Controller测试:
Controller测试则要使用到Mock测试,即对一些不易获取的对象采用虚拟的对象来创建进而方便测试。而Spring中提供的MockMvc则提供了对HTTP请求的模拟,使开发者能够在不依赖网络环境的情况下实现对Controller的测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @RunWith (SpringRunner. class ) @SpringBootTest public class HelloControllerTest2 { MockMvc mockMvc; @Autowired WebApplicationContext wac; @Autowired HelloServiceImpl helloService; @Before public void before() { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); } @Test public void test2() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get( "/hello" , "name=aaa" )) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } @Test public void test1() { System.out.println(helloService.sayHello( "里斯" )); } } |
注入一个WebApplicationContext用来模拟ServletContext环境。
声明一个MockMvc对象,并在每个测试方法执行前进行MockMvc的初始化操作
调用MockMvc中的perform方法开启一个RequestBuilder请求,具体的请求则通过MockMvcRequestBuilders进行构建,调用MockMvcRequestBuilders中的get方法表示发起一个GET请求,调用post方法则发起一个POST请求,其他的DELETE和PUT请求也是一样的,最后通过调用param方法设置请求参数。
利用MockMvcResultMatchers进行验证,这里表示验证响应码是否为200。
andDo(MockMvcResultHandlers.print())表示将请求详细信息打印到控制台。
andReturn()表示返回相应的MvcResult,并在下一行行将之获取并打印出来。
除了MockMvc这种测试方式之外,Spring Boot还专门提供了TestRestTemplate用来实现集成测试,若开发者使用了@Spring BootTest注解,则TestRestTemplate将自动可用,直接在测试类中注入即可。
注意,如果要使用TestRestTemplate进行测试,需要将@Spring BootTest注解中webEnvironment属性的默认值由WebEnvironment.MOCK修改为WebEnvironment.DEFINED_PORT或者WebEnvironment.RANDOM_PORT,因为这两种都是使用一个真实的Servlet环境而不是模拟的Servlet环境。其代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @RunWith (SpringRunner. class ) @SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class HelloControllerTest3 { @Autowired TestRestTemplate restTemplate; @Test public void test3() { ResponseEntity<String> hello = restTemplate.getForEntity( "/hello?name={0}" , String. class , "Michael" ); System.out.println(hello.getBody()); } } |
JSON测试:
开发者可以使用@JsonTest测试JSON序列化和反序列化是否工作正常,该注解将自动配置Jackson ObjectMapper、@JsonComponent以及Jackson Modules。如果开发者使用Gson代替Jackson,该注解将配置Gson。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @RunWith (SpringRunner. class ) @JsonTest public class JSONTest { @Autowired JacksonTester<Book> jacksonTester; @Test public void testSerialize() throws IOException { Book book = new Book(); book.setId( 1 ); book.setName( "三国演义" ); book.setAuthor( "罗贯中" ); Assertions.assertThat(jacksonTester.write(book)).isEqualToJson( "book.json" ); Assertions.assertThat(jacksonTester.write(book)).hasJsonPathStringValue( "@.name" ); Assertions.assertThat(jacksonTester.write(book)).extractingJsonPathStringValue( "@.name" ).isEqualTo( "三国演义" ); } @Test public void testDeserialize() throws Exception { String content = "{\"id\":1,\"name\":\"三国演义\",\"author\":\"罗贯中\"}" ; Assertions.assertThat(jacksonTester.parseObject(content).getName()).isEqualTo( "三国演义" ); } } |
添加@JsonTest注解,注入JacksonTester进行JSON的序列化和反序列化测试。
文章来源: Spring Boot+Vue全栈开发实战 - 8.3 单元测试
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)