如何使用JUnit5、@SpringBootTest测试@Valid?

问题描述 投票:0回答:1

这是我的控制器类。

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ValidController {

    @GetMapping("/valid")
    public ResponseEntity<String> valid(@RequestParam(required = false) @Valid @NotNull String firstName, @RequestParam(required = false) String lastName) {
        System.out.println("firstName = " + firstName);
        return ResponseEntity.ok(firstName);
    }
}

这是使用 MockMvc、@SpringBootTest 的测试代码

@SpringBootTest(classes = ValidController.class)
@AutoConfigureMockMvc
public class ValidControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    ServletModelAttributeMethodProcessor servletModelAttributeMethodProcessor;

    @Test()
    void validator_valid() throws Exception {
        mockMvc.perform(get("/valid")
                        .param("lastName", "foo"))
                .andExpect(status().is4xxClientError())
                .andReturn();
    }
}

所以问题就在这里。我知道我可以使用 @SpringBootTest 测试 @Valid 注释,但我不想简单地添加我制作的每个 bean。我想做的就是测试 ValidController,而不添加我制作的任何其他 bean。我怎样才能实现它?

我试过了

@Configuration
class TestConfig {
    @Bean
    public ServletModelAttributeMethodProcessor servletModelAttributeMethodProcessor() {
        return new ServletModelAttributeMethodProcessor(true);
    }
}

@SpringBootTest
        (classes = {ValidController.class
                , MethodValidationPostProcessor.class
                , ValidationAutoConfiguration.class
                , TestConfig.class
        }

@AutoConfigureMockMvc
public class ValidControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    ServletModelAttributeMethodProcessor servletModelAttributeMethodProcessor;

    @Test()
    void validator_valid() throws Exception {
        mockMvc.perform(get("/valid")
                        .param("lastName", "foo"))
                .andExpect(status().is4xxClientError())
                .andReturn();
    }
}
@Validated //this is added
@RestController
public class ValidController {

    @GetMapping("/valid")
    public ResponseEntity<String> valid(@RequestParam(required = false) @Valid @NotNull String firstName, @RequestParam(required = false) String lastName) {
        return ResponseEntity.ok(firstName);
    }
}

在这种情况下,测试抛出 ConstraintViolationException。但我不想在 Controller 类中添加@Validate,这在操作中是不必要的。如何在不使用@Validated的情况下在Controller中检查@Valid?

spring spring-boot validation junit
1个回答
0
投票

这就是

@WebMvcTest
的用途。它将仅引导所需的 MVC 部分和您的控制器,如果您有任何依赖项,请使用
@MockBean
来模拟它们。

其他一些技巧是不要使用参数,使用对象/dto 进行绑定和验证。让它变得更容易。

不要在控制器级别使用

@Validated
,因为它具有不同的目的,并且会导致不同的错误处理。 Spring Framework 6.2 包含对 MVC 和带注释参数的更好支持。

public class FormDto {

  @NotNull
  private String firstName;

  @NotNull
  private String lastName;

  // Getters + Setters omitted
}
@RestController
public class ValidController {

    @GetMapping("/valid")
    public ResponseEntity<String> valid(@Valid FormDto form) {
        System.out.println("firstName = " + form.getFirstName());
        return ResponseEntity.ok(form.getFirstName());
    }
}

测试

@WebMvcTest(ValidController.class)
public class ValidControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test()
    void validator_valid() throws Exception {
        mockMvc.perform(get("/valid")
                        .param("lastName", "foo"))
                .andExpect(status().is4xxClientError())
                .andReturn();
    }
}

这基本上就是您所需要的。使用表单对象使验证变得更容易,然后在方法中变得简单

@RequestParam

© www.soinside.com 2019 - 2024. All rights reserved.