SpringBoot项目中MockMVC 单元测试

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • SpringBoot项目中MockMVC 单元测试
  • 如何使用MockMVC单元测试
      • 添加依赖:在项目的pom.xml文件中添加Mockito和JUnit的依赖。
      • 创建测试类:在测试目录下创建一个新的测试类,例如MyServiceTest。
      • 创建Mock对象:在测试类中使用@Mock注解创建需要Mock的对象。
      • 初始化Mock对象:在测试类的@BeforeEach或@Before方法中初始化Mock对象。
      • 创建被测试的对象:在测试类中使用@InjectMocks注解创建被测试的对象,并将Mock对象注入到被测试对象中。
      • 编写测试方法:在测试类中编写测试方法,并使用Mock对象来模拟需要的行为。
      • 运行测试:在测试类中右键点击运行测试方法,或者使用Maven命令运行测试。
      • 下面是某个模块的增加和更新操作测试相关代码如下(示例):
  • 总结


SpringBoot项目中MockMVC 单元测试

在编写Springboot项目,如要对业务进行测试时,一般测试都是运行项目,通过URL在postman或者chrome浏览器进行测试,查看结果。

而当项目十分大的时候,我们在测试的时候,浪费的时间较多,因此我们通过使用SpringBoot MVC来进行单元测试。

可以实现对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。


如何使用MockMVC单元测试

Mock是一种用于模拟和替换类的对象的方法,以便在单元测试中独立于外部资源进行测试。使用Mock可以模拟各种对象,包括数据库连接、网络请求、外部服务调用等,以便在测试中检查代码的行为和输出。

以下是如何使用Mock来编写单元测试的步骤:

添加依赖:在项目的pom.xml文件中添加Mockito和JUnit的依赖。

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.12.4</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.8.1</version>
    <scope>test</scope>
</dependency>

创建测试类:在测试目录下创建一个新的测试类,例如MyServiceTest。

导入必要的类:在测试类中导入需要的类和注解。

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

创建Mock对象:在测试类中使用@Mock注解创建需要Mock的对象。

@Mock
private MyRepository myRepository;

初始化Mock对象:在测试类的@BeforeEach或@Before方法中初始化Mock对象。

@BeforeEach
void setUp() {
    MockitoAnnotations.openMocks(this);
}

创建被测试的对象:在测试类中使用@InjectMocks注解创建被测试的对象,并将Mock对象注入到被测试对象中。

@InjectMocks
private MyService myService;

编写测试方法:在测试类中编写测试方法,并使用Mock对象来模拟需要的行为。

@Test
void testSomeMethod() {
    // 设置Mock对象的行为
    when(myRepository.findById(1L)).thenReturn(Optional.of(new MyEntity()));
    
    // 调用被测试的方法
    MyEntity result = myService.findById(1L);
    
    // 断言结果
    assertNotNull(result);
}

运行测试:在测试类中右键点击运行测试方法,或者使用Maven命令运行测试。

这样就可以使用Mockito和JUnit来编写单元测试了。Mockito提供了丰富的API来模拟对象的行为,使得单元测试更加简单和可控。

下面是某个模块的增加和更新操作测试相关代码如下(示例):

public class ClassificationControllerTest {
    @InjectMocks
    private ClassificationController classificationController;
    
    private MockMvc mockMvc;
    @Mock
    private ClassificationService classificationService;
    
    private ClassificationDto classificationDto;
    
    private Gson gson = new Gson();

    @Before
    public void before(){
        /*
        首先,MockitoAnnotations.initMocks(this) 是一个静态方法,用于初始化当前类的所有带有
        @Mock 注解的 mock 对象。这个方法会自动扫描当前类中的所有字段,如果发现带有 @Mock 注解的
        字段,就会自动初始化该字段对应的 mock 对象
         */
        MockitoAnnotations.initMocks(this);
        /*
        mockMvc = MockMvcBuilders.standaloneSetup(classificationController) 创建了一个
        MockMvc 实例,用于模拟 Spring MVC 的请求和响应。classificationController 是被测试的
        控制器对象。

        setControllerAdvice(new LocalExceptionAspect(), new GlobalExceptionHandler())
        方法设置了两个 advices,用于处理控制器中抛出的异常。LocalExceptionAspect 是本地异常处理,
        GlobalExceptionHandler 是全局异常处理。
         */
        mockMvc = MockMvcBuilders.standaloneSetup(classificationController)
                .setControllerAdvice(new LocalExceptionAspect(), new GlobalExceptionHandler())
                .build();
        classificationDto = new ClassificationDto();
        classificationDto.setName("Test-Test");
        classificationDto.setDescription("这是一个测试");
        classificationDto.setColour("#ccc119");
    }

    @Test
    public void add() throws Exception {
        /*
        MockMvc 是一个用于模拟 Spring MVC 请求和响应的类。通过 mockMvc.perform() 方法,
        可以创建一个 MockMvc 请求对象,并指定请求的 URL、请求方法、请求头、请求体等参数。
         */
        MvcResult result= mockMvc.perform(MockMvcRequestBuilders.post("/classification/add") //请求方法为post ,请求的url
                        .accept(MediaType.APPLICATION_JSON) // 指定请求头Accept   指定请求头Content-Type
                        .contentType(MediaType.APPLICATION_JSON).content(gson.toJson(classificationDto))) //方法指定请求体位xxx对象的json字符串表示
                .andReturn(); //返回一个MvcResult对象
        int statusCode = result.getResponse().getStatus();
        String content = result.getResponse().getContentAsString();
        System.out.println("statusCode: "+statusCode);
        System.out.println("返回结果 content: "+content);
        Assert.assertEquals(200, statusCode);  //验证响应状态码是否为200,表示请求成功
        /*
          验证classificationService是否被调用了一次,并且传入的参数类型是ClassificationDto类型。
          这个方法用于确认在测试用例执行过程中,是否正确调用了相关的服务方法。
         */
        verify(classificationService,times(1)).add(any(ClassificationDto.class));
    }

    @Test
    public void update() throws Exception {
        classificationDto.setId(119L);
        MvcResult result= mockMvc.perform(MockMvcRequestBuilders.put("/classification/update")
                        .accept(MediaType.APPLICATION_JSON)
                        .contentType(MediaType.APPLICATION_JSON).content(gson.toJson(classificationDto)))
                .andReturn();
        int statusCode = result.getResponse().getStatus();
        String content = result.getResponse().getContentAsString();
        System.out.println("statusCode: "+statusCode);
        System.out.println("返回结果 content: "+content);
        Assert.assertEquals(200, statusCode);
        verify(classificationService,times(1)).update(any(ClassificationDto.class));
    }
}

总结

在上面的示例代码中,我们首先使用了@Mock和@InjectMock注解来创建Mock对象并注入到测试类中。然后,我们可以定义了Mock对象的期望行为,当被调用时,返回一个包含测试数据的Optional对象。接下来,我们调用了被测试的方法,并获取了返回值。最后,我们使用断言语句来检查方法的行为和输出,包括验证被调用了一次,并验证返回值是否符合预期。

使用Mock可以有效地模拟外部依赖,使测试更加可控和可重复。这有助于提高测试的可靠性,并帮助开发人员更好地理解代码的行为和输出。

你可能感兴趣的:(spring,boot,单元测试,log4j,mvc,java)