Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito error with method that returns Optional<T>

I have an interface with the following method

public interface IRemoteStore {

    <T> Optional<T> get(String cacheName, String key, String ... rest);

}

The instance of the class implementing the interface is called remoteStore.

When I mock this with mockito and use the method when:

Mockito.when(remoteStore.get("a", "b")).thenReturn("lol");

I get the error:

Cannot resolved the method thenReturn(java.lang.String)

I thought it has to do with the fact that get returns an instance of the Optional class so I tried this:

Mockito.<Optional<String>>when(remoteStore.get("cache-name", "cache-key")).thenReturn
        (Optional.of("lol"));

But, I get this error instead:

when (Optional<String>) in Mockito cannot be applied to (Optional<Object>).

The only time it worked was with this:

String returnCacheValueString = "lol";
Optional<Object> returnCacheValue = Optional.of((Object) returnCacheValueString);
Mockito.<Optional<Object>>when(remotestore.get("cache-name", "cache-key")).thenReturn(returnCacheValue);

But above returns an instance of Optional<Object> and not Optional<String>.

Why couldn't I just return an instance of Optional<String> directly? If I could, how should I go about doing that?

like image 812
Yu Lin Chen Avatar asked Jun 19 '15 19:06

Yu Lin Chen


2 Answers

Mocks that return have the expectation that the return type matches the mocked object's return type.

Here's the mistake:

Mockito.when(remoteStore.get("a", "b")).thenReturn("lol");

"lol" isn't an Optional<String>, so it won't accept that as a valid return value.

The reason it worked when you did

Optional<Object> returnCacheValue = Optional.of((Object) returnCacheValueString);
Mockito.<Optional<Object>>when(remotestore.get("cache-name", "cache-key")).thenReturn(returnCacheValue);

is due to returnCacheValue being an Optional.

This is easy to fix: just change it to an Optional.of("lol") instead.

Mockito.when(remoteStore.get("a", "b")).thenReturn(Optional.of("lol"));

You can also do away with the type witnesses as well. The result above will be inferred to be Optional<String>.

like image 153
Makoto Avatar answered Oct 06 '22 05:10

Makoto


Not sure why you are seeing errors, but this compiles/runs error-free for me:

public class RemoteStoreTest {
    public interface IRemoteStore {
        <T> Optional<T> get(String cacheName, String key);
    }
    public static class RemoteStore implements IRemoteStore {
        @Override
        public <T> Optional<T> get(String cacheName, String key) {
            return Optional.empty();
        }
    }

    @Test
    public void testGet() {
        RemoteStore remoteStore = Mockito.mock(RemoteStore.class);

        Mockito.when( remoteStore.get("a", "b") ).thenReturn( Optional.of("lol") );
        Mockito.<Optional<Object>>when( remoteStore.get("b", "c") ).thenReturn( Optional.of("lol") );

        Optional<String> o1 = remoteStore.get("a", "b");
        Optional<Object> o2 = remoteStore.get("b", "c");

        Assert.assertEquals( "lol", o1.get() );
        Assert.assertEquals( "lol", o2.get() );
        Mockito.verify(remoteStore);
    }
}
like image 30
Don Bottstein Avatar answered Oct 06 '22 06:10

Don Bottstein