java 如何使用JUnit测试@NotBlankSpring验证?

rqcrx0a6  于 2023-03-16  发布在  Java
关注(0)|答案(1)|浏览(95)

我正在尝试测试验证,我有一个控制器

@RestController
@RequestMapping("/product")
@RequiredArgsConstructor
@CrossOrigin
public class ProductController {

private final ProductService productService;

@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public ProductResponse createProduct(@RequestBody @Valid ProductRequest request) {
    return productService.createProduct(request);
 }
}

服务

@Slf4j
@Service
@RequiredArgsConstructor
public class ProductServiceImpl implements ProductService {

private final ProductMapper productMapper;
private final ProductRepository productRepository;

@Override
@Transactional
public ProductResponse createProduct(ProductRequest productRequest) {
    Product product = productMapper.mapToEntity(productRequest);
    Product savedProduct = productRepository.save(product);
    log.info("New product saved. Id = {}", savedProduct.getId());
    return productMapper.mapToResponse(savedProduct);
}

}

带有控制器和服务的Spring验证注解的DTO

@Getter
@Setter
public class ProductRequest {

    @NotBlank(message = "{name.not-blank}")
    private String name;

    @Positive(message = "{amount.positive}")
    private Integer amount;

    @Positive(message = "{price.positive}")
    private Double price;
}

www.example.com文件中的消息message.properties:

name.not-blank=Name field is required

在RestExceptionHandler中处理异常:

@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<ExceptionResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
    String message = ex.getAllErrors().stream()
            .map(DefaultMessageSourceResolvable::getDefaultMessage)
            .collect(Collectors.joining(", "));
    ExceptionResponse response = new ExceptionResponse(message);
    log.error(message);
    return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}

如果我启动应用程序,但没有填写ProductRequest的name字段,则会根据我的www.example.com文件收到消息messages.properties:“Name field is required”enter image description here
但是,如果我创建测试,并且在创建ProductRequest时没有填充相同的字段:

public class ProductServiceTest {

private final ProductRepository productRepository = mock(ProductRepository.class);
private final ProductMapper productMapper = new ProductMapperImpl();
private final ProductServiceImpl productService =
        new ProductServiceImpl(
                productMapper,
                productRepository);

@Test
void whenEmptyNameProduct() {
    var productRequest = buildProduct();
    var product = productMapper.mapToEntity(productRequest);
    when(productRepository.save(any())).thenReturn(product);
    var productResponse = productMapper.mapToResponse(product);
    MethodArgumentNotValidException thrown = assertThrows(
            MethodArgumentNotValidException.class,
            () -> productService.createProduct(productRequest));
    assertTrue(thrown.getMessage().contentEquals("Name field is required"));
}

private ProductRequest buildProduct() {
    ProductRequest request = new ProductRequest();
//        request.setName("");
    request.setAmount(0);
    request.setPrice(500.0);
    return request;
}

}

我从控制台收到消息:
org.opentest4j.AssertionFailedError:应引发org.springframework.web.bind.MethodArgumentNotValidException异常,但未引发任何异常。
enter image description here
我也尝试过从RestExceptionHandler中删除异常处理,然后启动应用程序,但在这种情况下,我得到了这样的消息:
已解决[org.springframework.web.bind.方法参数无效异常:验证公共com.guavapay.delivery.dto.response.ProductResponse com.guavapay.delivery.controller.ProductController.createProduct(com.guavapay.delivery.dto.request.ProductRequest)中的参数[0]失败:[对象'productRequest'中字段'name'上的字段错误:拒绝值[];代码[NotBlank.productRequest.name,NotBlank.name,非空白.java.lang.字符串,非空白];参数[org.springframework.context.support.默认消息源可解析:代码[productRequest.name,名称];参数[];默认消息[名称]];默认消息[名称字段为必填字段]] ]
enter image description here,其中包含方法参数无效异常。
我很困惑,我需要做什么来正确测试@NotBlank注解并获得MethodArgumentNotValidException以便在测试中Assert?
你能给我点建议吗?

sdnqo3pr

sdnqo3pr1#

看起来您好像绕过了Spring注入,所以我不希望像RestExceptionHandler这样的东西被调用。

@SpringBootTest
@ExtendWith(MockitoExtension.class)
public class ProductServiceTest {
   @Mock ProductRepository productRepository;
   @Autowired ProductMapper productMapper;
   @Autowired ProductServiceImpl productService;

   @Test
   void whenEmptyNameProduct() {
      //...same as before
   }
 }

我不知道您使用的是什么样的mock框架,但这是SpringBootMockito版本的样子。

相关问题