I'm trying to learn how to use Mockito and i'm hung up on how to go about verifying a method on a certain object was called X amount of times.
I have the following test code
verify(record, times(1)).setValue(Mockito.any(String.class),Mockito.any(String.class));
and the following piece of production code i'm trying to test
The string[]'s i'm setting up to iterate through
protected String[] columnNames = {"_id", "created_at", "updated_at", "name"};
protected ColumnType[] columnTypes = {ColumnType.INTEGER, ColumnType.TIMESTAMP, ColumnType.TIMESTAMP, ColumnType.TEXT};
and the production code that's in a loop, iterating through the String[]
for (int i = 0; i < columnCount; i++) {
if (columnNames[i].equals("_id")) {
record.setId(cursor.getInt(0));
} else {
switch (columnTypes[i]) {
case BOOL:
record.setValue(columnNames[i], cursor.getInt(i));
break;
case TEXT:
record.setValue(columnNames[i], cursor.getString(i));
break;
case INTEGER:
record.setValue(columnNames[i], cursor.getInt(i));
break;
case TIMESTAMP:
record.setValue(columnNames[i], cursor.getLong(i));
break;
case LONG:
record.setValue(columnNames[i], cursor.getLong(i));
break;
case DOUBLE:
record.setValue(columnNames[i], cursor.getDouble(i));
break;
default:
record.setValue(columnNames[i], "");
break;
}
}
}
And this is the error i get
testDataSourceCanFindRecord(com.test.app.DataSourceTest) Time elapsed: 0.081 sec <<< FAILURE! org.mockito.exceptions.verification.TooManyActualInvocations: customer.setValue(, ); Wanted 1 time: -> at com.test.app.DataSourceTest.testDataSourceCanFindRecord(DataSourceTest.java:141) But was 3 times. Undesired invocation: -> at com.test.core.DataSource.cursorToRecord(DataSource.java:210)
I'm expecting record.setValue(String key, String value) to be called once because of the "name" field in the String[]. What's happening is Mockito is registering record.setValue(String key, Long value) as the same thing as record.setValue(String key, String value), which is incorrect. Line 210 is the setValue in the TIMESTAMP case. How can i correct this?
If you look at the source code for InvocationMatcher , it looks like the logic to check method equality is a little more generous than you might think, and could ignore method overloading in some circumstances.
I'm not 100% sure, but try replacing any(String.class)
(which accepts any object of any type ) with isA(String.class)
, which will filter out invocations where that parameter is not a String. ( anyString
only checks its type in Mockito 2.0 and beyond.) Counterintuitively, any(Foo.class)
does not mean "anything as long as it's a Foo", it means "anything". This is due to change in Mockito 2.0.
Of course, you could also tighten up your verification so it checks that the key or value is equal to an expected value, but I'm not sure how possible that is in your case.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.