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种:
  1. MOCK,这种模式是当classpath下存在servletAPIS时,就会创建WebApplicationContext并提供一个mockservlet环境;当classpath下存在Spring WebFlux时,则创建ReactiveWebApplicationContext;若都不存在,则创建一个常规的ApplicationContext。
  2. RANDOM_PORT,这种模式将提供一个真实的Servlet环境,使用内嵌的容器,但是端口随机。
  3. DEFINED_PORT,这种模式也将提供一个真实的Servlet环境,使用内嵌的容器,但是使用定义好的端口。
  4. 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 单元测试

 

posted @   草木物语  阅读(3143)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示