You would need to provide more info, and maybe some actual code and/or config files, before you can expect specific answers. That said, based on the little you have provided, it sounds like the annotated bean is not being loaded.
Try adding the following to your test applicationContext.xml (or equivalent spring config file, if you are using one).
In short, if you are simply testing a controller and its methods then you can use the 'standaloneSetup' method which creates a simple Spring MVC configuration. This will not include your error handler that you annotate with @ControllerAdvice.
I had similar problem when trying to test ExceptionHandler annotated with @ControllerAdvice. In my case I had to add @Configuration file with @EnableWebMvc annotation to @ContextConfiguration on test class.
So my test looked like this:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
RestProcessingExceptionHandler.class,
TestConfiguration.class,
RestProcessingExceptionThrowingController.class })
public class TestRestProcessingExceptionHandler {
private MockMvc mockMvc;
@Autowired
WebApplicationContext wac;
@Before
public void setup() {
mockMvc = webAppContextSetup(wac).build();
}
@Configuration
// !!! this is very important - conf with this annotation
// must be included in @ContextConfiguration
@EnableWebMvc
public static class TestConfiguration { }
@Controller
@RequestMapping("/tests")
public static class RestProcessingExceptionThrowingController {
@RequestMapping(value = "/exception", method = GET)
public @ResponseBody String find() {
throw new RestProcessingException("global_error_test");
}
}
@Test
public void testHandleException() throws Exception {
mockMvc.perform(get("/tests/exception"))
.andExpect(new ResultMatcher() {
@Override
public void match(MvcResult result) throws Exception {
result.getResponse().getContentAsString().contains("global_error_test");
}
})
.andExpect(status().isBadRequest());
}
}
Suppose you have class MyControllerAdvice annotated with @ControllerAdvice that has methods annotated with @ExceptionHandler. For MockMvc you can easily add this class as exception resolver.
@tunguski sample code works but it pays to understand how things work. This is just one way to set things up.
@EnableWebMvc is equivalent to following in a spring configuration file
<mvc:annotation-driven />
Essentially for things to work you need to initialize Spring Mvc and load all your controllers and bean references. So following could be a valid setup as well as an alternate
Following is how you would setup the test class
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath: "classpath:test-context.xml" })
@WebAppConfiguration
public class BaseTest {
@Autowired
WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
And following could be the spring configuration for the test
As a result, Spring test introduced the ability to register @ControllerAdvice classes in the builder in 4.2. If you are using Spring Boot then you will need 1.3.0 or later.
With this improvement, if you are using standalone setup then you can set one or more ControllerAdvice instances like so:
I am using Spring Boot 2.x, but it seems MockMvcBuilders is not required anymore or as we are defining the ControllerAdvice as part of the Configuration, it gets loaded.
@WebMvcTest
@ContextConfiguration(classes = {
UserEndpoint.class, //the controller class for test
WebConfiguration.class, //security configurations, if any
StandardRestExceptionInterpreter.class. //<-- this is the ControllerAdvice class
})
@WithMockUser(username = "test@asdf.com", authorities = {"DEFAULT"})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserEndpointTests {
@Test
@Order(3)
public void shouldThrowExceptionWhenRegisteringDuplicateUser() throws Exception {
//do setup...
Mockito.doThrow(EntityExistsException.class).when(this.userService).register(user);
this.mockMvc
.perform(MockMvcRequestBuilders
.post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content(this.objectMapper.writeValueAsString(user)))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isConflict());
}
}