Affects: current, see https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/mock/mockito/MockBean.html
I am trying to get my mock to return a custom exception for every method call.
This should be fairly easy by passing it a custom answer
implementation which implements Answer<Object>
and overrides public Object answer(InvocationOnMock invocation) throws Throwable
.
For example consider this example modeled after org.mockito.Answers
(which is referenced in the API doc):
package com.foo.utils;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public enum ExceptionAnswers implements Answer<Object> {
RUNTIME_EXCEPTION(new RuntimeExceptionAnswer());
private final Answer<Object> implementation;
ExceptionAnswers(Answer<Object> implementation) {
this.implementation = implementation;
}
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return implementation.answer(invocation);
}
public static class RuntimeExceptionAnswer implements Answer<Object> {
public Object answer( InvocationOnMock invocation ) {
throw new RuntimeException ( invocation.getMethod().getName() + " threw RuntimeException" );
}
}
}
and its usage as for example
package com.allianz.cee.sme.controller;
import com.foo.service.CompanyService;
import com.foo.utils.ExceptionAnswers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import static io.restassured.module.mockmvc.RestAssuredMockMvc.given;
@SpringBootTest
@AutoConfigureMockMvc
class CompanyControllerTest {
@Autowired
MockMvc mockMvc;
@MockBean(answer = ExceptionAnswers.RUNTIME_EXCEPTION)
CompanyService mockService;
@Test
void doSomething(){...}
}
However, this will give me the following error: Incompatible types. Found: 'com.foo.utils.ExceptionAnswers', required: 'org.mockito.Answers'
This hard dependency on the mockito.Answers enum prevents any extension and customization as an enum can not be extended.
Now the great thing is that mockito.Answers already implements Answer<Object>
so all that needs to be done is to change the type of @MockBean's answer
field.
Please let me know if you need more information.
Cheers!
Comment From: jnizet
That wouldn't be valid Java code.
An annotation type element can only be a primitive type, a String, a Class, an enum type, an annotation type or an array type whose component type is one of the preceding types.
See https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.1.
Comment From: snicoll
That and MockBean
is part of Spring Boot so there's nothing actionable here.