问题
I am having a simple Spring boot application which contains Employee controller which returns the Employee names if the year passed is greater than 2014 and if the it is not less than 2014 then I am throwing a custom exception and handling it in Exception Handler.
I want to unit test the exception flow using powermock but I am not sure how to do it. I have gone through some links but unable to understand.
Currently I am getting java.lang.IllegalArgumentException: WebApplicationContext is required.
EmployeeController.java
@RestController
public class EmployeeController{
@GetMapping(value = "/employee/{joiningYear}",produces = MediaType.APPLICATION_JSON_VALUE)
public List<String> getEmployeeById(@PathVariable int joiningYear) throws YearViolationException {
if(joiningYear < 2014){
throw new YearViolationException("year should not be less than 2014");
}else{
// send all employee's names joined in that year
}
return null;
}
}
ExceptionHandler
@RestControllerAdvice
public class GlobalControllerExceptionHandler {
@ExceptionHandler(value = { YearViolationException.class })
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiErrorResponse yearConstraintViolationExceptio(YearViolationException ex) {
return new ApiErrorResponse(400, 5001, ex.getMessage());
}
}
CustomException
public class YearViolationException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public YearViolationException(String message) {
super(message);
}
}
Junit to unit test exception handler
@RunWith(PowerMockRunner.class)
@WebAppConfiguration
@SpringBootTest
public class ExceptionControllerTest {
@Autowired
private WebApplicationContext applicationContext;
private MockMvc mockMVC;
@Before
public void setUp() {
mockMVC = MockMvcBuilders.webAppContextSetup(applicationContext).build();
}
@Test
public void testhandleBanNotNumericException() throws Exception {
mockMVC.perform(get("/employee/2010").accept(MediaType.APPLICATION_JSON)).andDo(print())
.andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON));
}
}
回答1:
As stated by others, you don't need mockMVC at all. If you want to test REST endpoints, what you need is TestRestTemplate. Runwith SpringRunner.class is important as well as the WebEnvironment setup.
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class RestServiceApplicationTests {
private String baseUrl = "http://localhost:8090";
private String endpointToThrowException = "/employee/2010";
@Autowired
private TestRestTemplate testRestTemplate;
@Test(expected = YearViolationException.class)
public void testhandleBanNotNumericException() {
testRestTemplate.getForObject(baseUrl + endpointToThrowException, String.class);
}
回答2:
From how your setup looks, you don't need to use Mocks at all. It seem's like you want to load the complete application context and use mockMVC to send requests against your rest controller. This is actually and integrationtest!
Now, unfortunately we use Spring Boot 1.3 here, so I'm not sure if the combination of @RunWith(PowerMockRunner.class)
and @SpringBootTest
in fact loads the Application context. Check your logs and see if it does and if not, try this:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
If, on the other hand you want to make a simple unit test, then you don't need to load the application context. Instead you can just use regular Mockito with @Mock
and @InjectMocks
in conjuntion with @RunWith(MockitoJUnitRunner.class)
and call the method you want to test directly as you would any other method under test.
Hope this help.
来源:https://stackoverflow.com/questions/43911326/how-to-unit-testing-spring-boot-rest-controller-and-exception-handler-using-powe