When I create a case where exception is thrown by the code by calling APIs, at that time, ExceptionHandler
is invoked as expected. But when I try creating the same case through unit tests, at that time, ExceptionHandler
is not invoked. My classes are as below:
Controller.java
@Post("/XXX")
public ResponseEntity<List<CategoryTopicBean>> listCategoryTopics(@Body CategoryIdsRequestBean categoryIdsRequestBean) {
if (categoryIdsRequestBean.getCategoryIds().size() > MAX_ALLOWED_CATEGORY_SELECTION) {
throw new CustomException(SystemConstants.ResponseCode.ERROR, SystemConstants.ResponseMessage.OVERFLOW_MAX_CATEGORIES);
}
...
CustomExceptionHandler.java:
@Produces
@Singleton
@Requires(classes = {CustomException.class, ExceptionHandler.class})
public class CustomExceptionHandler implements ExceptionHandler<CustomException, HttpResponse> {
@Override
public HttpResponse handle(HttpRequest request, CustomException exception) {
return HttpResponse.ok(new ResponseEntity<>(exception.responseCode, exception.getMessage()));
}
}
XXXShould.java
@Test
public void should_list_category_topics() {
CategoryIdsRequestBean categoryIdsBean = new CategoryIdsRequestBean();
IdBean idBean = new IdBean();
idBean.setId(ID_1);
categoryIdsBean.setCategoryIds(Arrays.asList(idBean));
ResponseEntity<List<CategoryTopicBean>> responseEntity = topicController.listCategoryTopics(categoryIdsBean);
assertThat(SystemConstants.ResponseCode.SUCCESS).isEqualTo(responseEntity.getResponseCode());
assertThat(1).isEqualTo(responseEntity.getData().size());
categoryIdsBean = new CategoryIdsRequestBean();
categoryIdsBean.setCategoryIds(Arrays.asList(idBean, idBean, idBean, idBean, idBean, idBean));
responseEntity = topicController.listCategoryTopics(categoryIdsBean);
}
Can anyone please look into this, and help me out?
The problem here is, you are testing the controller by directly invoking the controller method
topicController.listCategoryTopics(categoryIdsBean)
.
This is not a good approach to test controller functionality. What you should do is use MicronautTest. MicronautTest will start an embedded server. Now you can use an HTTP client to hit the endpoint and retrieve the result.
Your code needs to be changed to something around the lines as below.
@MicronautTest
class HelloWorldTest {
@Inject
@Client("/")
RxHttpClient client;
@Test
public void should_list_category_topics() {
// Test Data
CategoryIdsRequestBean categoryIdsBean = new CategoryIdsRequestBean();
IdBean idBean = new IdBean();
idBean.setId(ID_1);
categoryIdsBean.setCategoryIds(Arrays.asList(idBean));
HttpRequest<String> request = HttpRequest.POST("/XXX", categoryIdsBean);
ResponseEntity<List<CategoryTopicBean>> retrieve = client.toBlocking().retrieve(request, ResponseEntity.class);
categoryIdsBean = new CategoryIdsRequestBean();
categoryIdsBean.setCategoryIds(Arrays.asList(idBean, idBean, idBean, idBean, idBean, idBean));
responseEntity = topicController.listCategoryTopics(categoryIdsBean);
}
}
For the exception
case scenario, as the exception handler returns ResponseEntity<String>
, you would need to make a minor change in the above code.
ResponseEntity<String> retrieve = client.toBlocking()
.retrieve(request, ResponseEntity.class);
If your controller calls any other service, do not forget to mock the behavior.