简体   繁体   中英

Mockito verifying method calls

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM