Tharindu Eranga
Tharindu Eranga

Reputation: 167

Springboot Mockito Test and Autowired messageSource in controller org.springframework.context.NoSuchMessageException

I have a Springboot app with REST controller and Mockito unit test cases written for it. The problem is I am getting NoSuchMessageException by reading messageSource in the RestController when running the test cases. But not happening when calling it in actually using Postman or other Rest clients. (I use Lombok to avoid boilerplate codes).

The Rest Controller code

@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());
    }

}

The messageSource Config

@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;
    }
}

Test class

@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());
    }
}

Exception

org.springframework.context.NoSuchMessageException: No message found under code 'success.confirmation.common.added.code' for locale 'en_US'.

But above message exists and successfully appears in actual REST clients.

Project structure

enter image description here

Thanks in advance.

Upvotes: 5

Views: 2814

Answers (1)

rieckpil
rieckpil

Reputation: 12051

The @WebMvcTest annotation only loads relevant beans (e.g. Filter, @ControllerAdvice, WebMvcConfigurer) for testing your controller. By default, this TestContext doesn't include any custom @Configuration beans.

You have explicitly import your config:

@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

}

In case you're relying on the auto-configuration of the MessageSource you can enable it for your test with @ImportAutoConfiguration(MessageSourceAutoConfiguration.class).

Upvotes: 6

Related Questions