Springboot Mockito 测试和控制器 org.springframework.context.NoSuchMessageException 中的 Autowired messageSource

Tha*_*nga 4 unit-testing spring-test mockito spring-boot junit5

我有一个带有 REST 控制器的 Springboot 应用程序和为其编写的 Mockito 单元测试用例。问题是我在运行测试用例时通过读取 RestController 中的 messageSource 得到 NoSuchMessageException 。但实际使用 Postman 或其他 Rest 客户端调用它时不会发生。(我使用 Lombok 来避免样板代码)。

其余控制器代码

@RestController
@RequestMapping(value = VERSION + "/product")
@Slf4j
@RequiredArgsConstructor
public class ProductController implements CommonController {

    private final ProductService productService;

    private final MessageSource messageSource;

    
    @PostMapping(path = "")
    public ResponseEntity<CommonResponseDTO> saveProduct(@Valid @RequestBody ProductSaveRequest request) {
        return addNewProduct(request);
    }
    
    private String getMessage(String key) {
        return messageSource.getMessage(key, new Object[0], Locale.getDefault());
    }

}
Run Code Online (Sandbox Code Playgroud)

消息源配置

@Configuration
public class AppConfig {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("classpath:messages/exception-message", "classpath:messages/success-message");
        messageSource.setCacheSeconds(60); //reload messages every 60 seconds
        return messageSource;
    }
}
Run Code Online (Sandbox Code Playgroud)

测试班

@Slf4j
@ExtendWith(SpringExtension.class)
@WebMvcTest(value = ProductController.class)
class ProductControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private ProductService productService;

    private static final String PRODUCT_PATH = "/v1/product";
    
@Test
    void saveProduct() throws Exception {

        // productService.add to respond back with mockProduct
        Mockito.doNothing().when(productService).add(Mockito.any(Product.class));

        // Send course as body to /students/Student1/courses
        RequestBuilder requestBuilder = MockMvcRequestBuilders
                .post(PRODUCT_PATH)
                .accept(MediaType.APPLICATION_JSON)
                .content("{\n" +
                        "  \"name\": \"Apple\"\n" +
                        "}")
                .contentType(MediaType.APPLICATION_JSON);

        MvcResult result = mockMvc.perform(requestBuilder).andReturn();

        MockHttpServletResponse response = result.getResponse();

        assertEquals(HttpStatus.CREATED.value(), response.getStatus());
    }
}
Run Code Online (Sandbox Code Playgroud)

例外

org.springframework.context.NoSuchMessageException: No message found under code 'success.confirmation.common.added.code' for locale 'en_US'.
Run Code Online (Sandbox Code Playgroud)

但上述消息存在并成功出现在实际的 REST 客户端中。

项目结构

在此输入图像描述

提前致谢。

rie*_*pil 5

@WebMvcTest注释仅加载相关的 bean(例如Filter@ControllerAdviceWebMvcConfigurer)来测试您的控制器。默认情况下,此 TestContext 不包含任何自定义@Configurationbean。

您已明确导入您的配置:

@Slf4j
// @ExtendWith(SpringExtension.class) not needed as part of @WebMvcTest with recent Spring Boot versions
@Import(AppConfig.class)
@WebMvcTest(value = ProductController.class)
class ProductControllerTest {
   
  // your test

}
Run Code Online (Sandbox Code Playgroud)

如果您依赖于自动配置,MessageSource您可以使用 来启用它进行测试@ImportAutoConfiguration(MessageSourceAutoConfiguration.class)