Mockito showing 0 interactions with mock - java

Here is my code:
public class S3Dao {
private final AmazonS3Client amazonS3Client;
static final String BUCKET_NAME = "myBucket";
public S3Dao(final AmazonS3Client amazonS3Client) {
this.amazonS3Client = amazonS3Client;
}
public void put(ModelObject modelObject, String playlistId) {
this.amazonS3Client.putObject(BUCKET_NAME, playlistId, new Gson().toJson(modelObject));
}
}
And my test code:
#ExtendWith(MockitoExtension.class)
public class S3DaoTest {
private S3Dao s3Dao;
#Mock
private AmazonS3Client s3Client;
#BeforeEach
public void beforeEach() {
this.s3Dao = new S3Dao(this.s3Client);
}
#Test
public void putTest() {
ModelObject obj = new ModelObject("name", new ArrayList<>());
String json = new Gson().toJson(obj);
verify(s3Client).putObject(S3Dao.BUCKET_NAME, "playlistId", json);
this.s3Dao.put(obj, "playlistId");
}
}
The resulting error is
Wanted but not invoked:
s3Client.putObject(
"myBucket",
"playlistId",
"{"name":"name","children":[]}"
);
-> at com.amazon.amazon.live.destination.playlist.dao.S3DaoTest.putTest(S3DaoTest.java:34)
Actually, there were zero interactions with this mock.
Indeed, removing the verify causes the test to pass without issue. Why isn't this working?

Move the verify after the method call
#Test
public void putTest() {
ModelObject obj = new ModelObject("name", new ArrayList<>());
String json = new Gson().toJson(obj);
this.s3Dao.put(obj, "playlistId");
verify(s3Client).putObject(S3Dao.BUCKET_NAME, "playlistId", json);
}

Related

Apache Beam , mock external Clients initialized in #Setup Lifecycle method of DoFn

I have created the following DoFn class, but i am not sure, how to mock APIClient, since creating the instance of JsonToGenericRecordMapper in Junit with mocked APICall object, is getting overridden with #setup method, which is creating actual instance of APICall ?
public class JsonToGenericRecordMapper extends DoFn<String, GenericRecord> {
private APICall apiCall;
#setup
public void setup ()
{
api = new APICall();
}
#ProcessElement
public void processElement(ProcessContext processContext) {
String enrichedItemCost = processContext.element();
Schema schema = CommonUtils.schema;
GenericRecord genericRecord = new GenericData.Record(schema);
genericRecord.put(CommonUtils.SCHEMA_FIELD_KEY, enrichedItemCost);
processContext.output(genericRecord);
}
}
TestPipeline testPipeline = TestPipeline.create();
APICAll apiCall = Mockito.mock(APICall.class);
dataPCollection.apply(new JsonToGenericRecordMapper(apiCall));
you can create two constructors (an empty and one one with the APICall parameter), and use one of them for testing, something like that (I just extended your example to get the point, so it's just an example):
public class JsonToGenericRecordMapper extends DoFn<String, GenericRecord> {
private APICall apiCall;
public JsonToGenericRecordMapper() {
}
public JsonToGenericRecordMapper(APICall apiCall) {
this.apiCall = apiCall;
}
#setup
public void setup ()
{
if(apiCall==null) {
api = new APICall();
}
}
#ProcessElement
public void processElement(ProcessContext processContext) {
String enrichedItemCost = processContext.element();
Schema schema = CommonUtils.schema;
GenericRecord genericRecord = new GenericData.Record(schema);
genericRecord.put(CommonUtils.SCHEMA_FIELD_KEY, enrichedItemCost);
processContext.output(genericRecord);
}
}
TestPipeline testPipeline = TestPipeline.create();
APICAll apiCall = Mockito.mock(APICall.class);
dataPCollection.apply(new JsonToGenericRecordMapper(apiCall));

Mockito dateformat returning incorrect month; assertEquals fails

I am trying to mock DateFormat using mockito. I just want the current month to be displayed. In my Junit test, I'm doing the following in my Junit test :
#Before
public void setUp() throws Exception {
reportQueryParams = ReportQueryParams.builder()
.id("07")
.build();
}
#Test
public void tabSerializerTest() {
DateFormat formatter = Mockito.mock(SimpleDateFormat.class);
StringBuffer stringBuffer = new StringBuffer("July");
Mockito.when(formatter.format(Mockito.any(Date.class), Mockito.any(StringBuffer.class),
Mockito.any(FieldPosition.class))).thenReturn(stringBuffer);
MetricsSerializer metricsSerializer = new MetricsSerializer();
String tabSeparated = metricsSerializer.serializeMetrics(reportQueryParams);
String expected = new StringBuilder().append("074")
.append("\t")
.append("July")
.toString();
assertEquals(expected, tabSeparated);
}
The function which I am testing:
public String serializeMetrics(final ReportQueryParams reportQueryParams) {
stringJoiner = new StringJoiner("\t");
addValueFromString(reportQueryParams.getId());
addValueFromString(getCurrentMonth());
return stringJoiner.toString();
}
private String getCurrentMonth() {
DateFormat monthFormat = new SimpleDateFormat("MMMMM");
return monthFormat.format(new Date());
}
private void addValueFromString(final String value) {
stringJoiner.add(value);
}
My ReportQueryParams class:
public class ReportQueryParams {
private String id;
}
I am getting "August" as the month returned from the function. Hence, the assertEquals is failing. How can I fix this?
The problem here is that at no point does the mock end up in the class under test so the arranged behavior is not being invoked.
That is because you are creating the formatter withing the method under test
DateFormat monthFormat = new SimpleDateFormat("MMMMM");
tightly coupling the class to the dependency, which makes testing difficult but not impossible.
Unfortunately PowerMockito allows things like this
SimpleDateFormat formatter = mock(SimpleDateFormat.class);
when(formatter.format(any(Date.class)).thenReturn("July");
PowerMockito.whenNew(SimpleDateFormat.class).withArguments(anyString()).thenReturn(formatter);
//...Do not forget to include #PrepareForTest(SimpleDateFormat.class) on the test class
When ideally what you should be doing is refactoring the class to expose any explicit dependencies, either via construct or method arguments, that can injected into the subject under test.
public interface MonthProvider {
private String getCurrentMonth();
}
public class DefaultMonthProvider implements MonthProvider {
DateFormat monthFormat = new SimpleDateFormat("MMMMM");
public String getCurrentMonth() {
return monthFormat.format(new Date());
}
}
public class MetricsSerializer {
MonthProvider provider;
public MetricsSerializer(MonthProvider provider) {
this.provider = provider;
}
public String serializeMetrics(final ReportQueryParams reportQueryParams) {
stringJoiner = new StringJoiner("\t");
addValueFromString(reportQueryParams.getId());
addValueFromString(provider.getCurrentMonth());
return stringJoiner.toString();
}
private void addValueFromString(final String value) {
stringJoiner.add(value);
}
}
that can be injected into the subject under test.
#Before
public void setUp() throws Exception {
reportQueryParams = ReportQueryParams.builder()
.id("07")
.build();
}
#Test
public void tabSerializerTest() {
//Arrange
MonthProvider privider = Mockito.mock(MonthProvider.class);
Mockito.when(provider.getCurrentMonth()).thenReturn("July");
MetricsSerializer metricsSerializer = new MetricsSerializer(provider);
String expected = new StringBuilder().append("07")
.append("\t")
.append("July")
.toString();
//Act
String actual = metricsSerializer.serializeMetrics(reportQueryParams);
//Assert
assertEquals(expected, actual);
}

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: ArrayList cannot be returned by getDetails()

here is code
public class TodoBusinessImpl {
BusinessManager businessManager;
public TodoBusinessImpl(BusinessManager businessManager) {
this.businessManager = businessManager;
}
public List<String> retrieveTodosRelatedToSpring(String user) {
List<String> filteredTodos = new ArrayList<String>();
Map<String, String> test = businessManager.getDetails();
return filteredTodos;
}
}
what is wrong with that? what i am doing wrong
public class MockitoTest {
private BusinessManager businessManager;
#Before
public void setUp() {
businessManager = Mockito.mock(BusinessManager.class);
}
#Test
public void retrieveTodosRelatedToSpringTest() {
TodoBusinessImpl todoBusinessImpl = new TodoBusinessImpl(businessManager);
Mockito.when(todoBusinessImpl.retrieveTodosRelatedToSpring("test"))
.thenReturn(Arrays.asList("test"));
}
}
This is the test class. Getting exception that org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ArrayList cannot be returned by getDetails()
You have to call the method that you're testing not mock it's behavior "not tell it what to do when it's called".
Instead of:
Mockito.when(todoBusinessImpl.retrieveTodosRelatedToSpring("test")).thenReturn(Arrays.asList("test"));
You should do this:
List<String> list = todoBusinessImpl.retrieveTodosRelatedToSpring("test");
// print list or assert it's content to make sure you're getting the right response

Mockito doReturn always return NULL

I have a class that I wish to test using Mockito. The problem I am facing is that when the Mock is called it always returns a null value.
I can see when I debug that Mockito see the mock but always returns null. My understanding is that in the CUT that when the client.sendMessage is called it will return the value for Transaction that I have created in the #Test.
Any suggestions on what I am doing wrong?
The class under test:
public String SendMessage(String ID, String body) {
String receipt = null;
Map<String, Integer> Transaction = null;
try {
Transaction = client.sendMessage(ID, body);
} catch(Exception e) {
receipt = "FAIL";
return receipt;
}
receipt = Transaction.get("receipt").toString();
return receipt;
}
My test method is:
#Mock
private MessageSenderClient client;
#InjectMocks
MessageSender ms;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testPushNotificationProcessorTransactionID() {
String Id = "1234";
String body = "Test Message";
Map<String, Integer> Transaction = new HashMap<String, Integer>();
Transaction.put("Id", 123456);
client = Mockito.mock(PushNotificationClient.class);
Mockito.doReturn(Transaction).when(client).sendMessage(Matchers.anyString(), Matchers.anyString());
String transactionID = ms.SendPushMessage(Id, body);
assertEquals(transactionID, "1");
}

Mockito / Spring MVC - (annotation-driven) request mapping dynamic verification

I'm currently writing a Spring MVC-based webapp.
Rather than writing one test for every annotated method, I would like to benefit from Parameterized JUnit runner.
Finally, I got it almost working, although I had to change all primitive arguments to their wrapper counterpart in my controller methods (and then manually do the sanity checks on null refs).
If it can help, here is the code (this also depends on Guava):
#RunWith(Parameterized.class)
public class MyControllerMappingTest {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private MyController mockedController;
private AnnotationMethodHandlerAdapter annotationHandlerAdapter;
private final String httpMethod;
private final String uri;
private final String controllerMethod;
private final Class<?>[] parameterTypes;
private final Object[] parameterValues;
#Before
public void setup() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
mockedController = mock(MyController.class);
annotationHandlerAdapter = new AnnotationMethodHandlerAdapter();
}
#Parameters
public static Collection<Object[]> requestMappings() {
return asList(new Object[][] {
{"GET", "/my/uri/0", "index", arguments(new MethodArgument(Integer.class, 0))}
});
}
private static List<MethodArgument> arguments(MethodArgument... arguments) {
return asList(arguments);
}
public MyControllerMappingTest(String httpMethod, String uri, String controllerMethod, List<MethodArgument> additionalParameters) {
this.httpMethod = httpMethod;
this.uri = uri;
this.controllerMethod = controllerMethod;
this.parameterTypes = new Class<?>[additionalParameters.size()];
initializeParameterTypes(additionalParameters);
this.parameterValues = newArrayList(transform(additionalParameters, valueExtractor())).toArray();
}
private void initializeParameterTypes(List<MethodArgument> additionalParameters) {
Iterable<Class<?>> classes = transform(additionalParameters, typeExtractor());
int i = 0;
for (Class<?> parameterClass : classes) {
parameterTypes[i++] = parameterClass;
}
}
#Test
public void when_matching_mapping_constraints_then_controller_method_automatically_called() throws Exception {
request.setMethod(httpMethod);
request.setRequestURI(uri);
annotationHandlerAdapter.handle(request, response, mockedController);
Method method = MyController.class.getMethod(controllerMethod, parameterTypes);
method.invoke(verify(mockedController), parameterValues);
}
}
with the custom class MethodArgument that follows:
public class MethodArgument {
private final Class<?> type;
private final Object value;
public MethodArgument(final Class<?> type, final Object value) {
this.type = type;
this.value = value;
}
public Object getValue() {
return value;
}
public Class<?> getType() {
return type;
}
public static Function<MethodArgument, Class<?>> typeExtractor() {
return new Function<MethodArgument, Class<?>>() {
#Override
public Class<?> apply(MethodArgument argument) {
return argument.getType();
}
};
}
public static Function<MethodArgument, Object> valueExtractor() {
return new Function<MethodArgument, Object>() {
#Override
public Object apply(MethodArgument argument) {
return argument.getValue();
}
};
}
}
So, I'm almost there, the only test case here works because of Java Integer cache, and the Integer instance is therefore the same throughout the call chain... This however doesn't work with custom objects, I always end up with an InvocationTargetException (cause: "Argument(s) are different!")...
The types are correct but the passed instances are not identical to the ones set in the #Parameters method.
Any idea how to work around this?
Hold your horses!
SpringSource is baking a spring-test-mvc module :
https://github.com/SpringSource/spring-test-mvc
It would be nice if instead of providing the example that works, you could provide the one that doesn't, and provide the stacktrace as well.
I quickly checked Google, it seems that Mockito doesn't handle well reflection on spy objects.
If you really wanna go along that road, there might be another way: providing the expected called method as part of your parameterized data, not by providing reflection data, but by actually calling the mock from there.
I'm writing that without any IDE at hand, so there might be compile errors, but you'll get the idea:
#RunWith(Parameterized.class)
public class MyControllerMappingTest {
public interface VerifyCall<T> {
void on(T controller);
}
#Parameters
public static Collection<Object[]> requestMappings() {
Object[][] testCases = {
{"GET", "/my/uri/0", new VerifyCall<MyController>() {
#Override
public void on(MyController controller) {
controller.index(0);
}
}}
};
return asList(testCases);
}
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private MyController mockedController;
private AnnotationMethodHandlerAdapter annotationHandlerAdapter;
private final String httpMethod;
private final String uri;
private final VerifyCall<MyController> verifyCall;
public MyControllerMappingTest(String httpMethod, String uri, VerifyCall<MyController> verifyCall) {
this.httpMethod = httpMethod;
this.uri = uri;
this.verifyCall = verifyCall;
}
#Before
public void setup() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
mockedController = mock(MyController.class);
annotationHandlerAdapter = new AnnotationMethodHandlerAdapter();
}
#Test
public void when_matching_mapping_constraints_then_controller_method_automatically_called() throws Exception {
request.setMethod(httpMethod);
request.setRequestURI(uri);
annotationHandlerAdapter.handle(request, response, mockedController);
verifyCall.on(verify(mockedController));
}
}
Of course, having Java Lambas would help making this more readable.
You could also use FunkyJFunctional :
#RunWith(Parameterized.class)
public class MyControllerMappingTest {
#Parameters
public static Collection<Object[]> requestMappings() {
class IndexZero extends FF<MyController, Void> {{ in.index(0); }}
Object[][] testCases = { //
{"GET", "/my/uri/0", withF(IndexZero.clas)}
};
return asList(testCases);
}
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private MyController mockedController;
private AnnotationMethodHandlerAdapter annotationHandlerAdapter;
private final String httpMethod;
private final String uri;
private final Function<MyController, Void> verifyCall;
public MyControllerMappingTest(String httpMethod, String uri, Function<MyController, Void> verifyCall) {
this.httpMethod = httpMethod;
this.uri = uri;
this.verifyCall = verifyCall;
}
#Before
public void setup() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
mockedController = mock(MyController.class);
annotationHandlerAdapter = new AnnotationMethodHandlerAdapter();
}
#Test
public void when_matching_mapping_constraints_then_controller_method_automatically_called() throws Exception {
request.setMethod(httpMethod);
request.setRequestURI(uri);
annotationHandlerAdapter.handle(request, response, mockedController);
verifyCall.apply(verify(mockedController));
}
}
A few side notes:
For the sake of readability, it's a good practice to put your static members first in your class. Instance methods (setup()) should also go after the constructor.
Array syntax:
Instead of this syntax:
return asList(new Object[][] {
{},
{}
};
I find this syntax to be more readable:
Object[][] testCases = {
{},
{}
};
return asList(testCases);

Categories

Resources