Question

I started to use Guava Optional as a part of the null object pattern and would like to improve the use in Mockito, where null is the default return value for mocked objects. To behave correctly one needs to explicitly tell Mockito to use Optional.absent() instead:

import org.mockito.*;
import org.testng.*;
import org.testng.annotations.*;
import com.google.common.base.Optional;


public class Example {

    @Mock
    private MyObject underTest;

    @Test
    public void testExample() {
        // fails
        // assertNotNull(underTest.get());

        Mockito.when(underTest.get()).thenReturn(Optional.absent());
        Assert.assertNotNull(underTest.get());
    }

    public class MyObject {

        public Optional<Object> get() {
            return Optional.absent();
        }
    }

    @BeforeClass
    public void beforeClass() {
        MockitoAnnotations.initMocks(this);
    }
}

Is there a easy way to improve mockito to automatically return Optional.absent() instead of null if the actual type is Optional?

Was it helpful?

Solution

I tried to solve it with reflection in @Before annotated method, however, I didn't manage to get it working.

Solution you found out can be improved by creating your own static factory that creates mocks with an OptionalAnswer and use it instead of default Mockito factory:

class MockitoOptional{
    public static <T> T mock(Class<T> classToMock) {
       return Mockito.mock(classToMock, new OptionalAnswer());
    }
}

Next step will be to extend a test runner that will use this factory to inject mocks into @Mock annotated fields. Search for custom JUnit test runners if you haven't heard of them yet.

OTHER TIPS

I got a first shot with the linked answer for strings.

public class OptionalAnswer extends ReturnsEmptyValues {

    @Override
    public Object answer(InvocationOnMock invocation) {
        Object answer = super.answer(invocation);
        if (answer != null) {
            return answer;
        }
        Class<?> returnType = invocation.getMethod().getReturnType();
        if (returnType == Optional.class) {
            return Optional.absent();
        }
        return null;
    }
}


@Test
public void testExample() {
    MyObject test = mock(MyObject.class, new OptionalAnswer());
    Assert.assertNotNull(test.get());
}

Won't get much easier, right?

Mockito.when(underTest.get()).thenReturn(Optional.<Object>absent());

This is all you need to do. Add the type returned from underTest.get() to your absent() call. Yes it is supposed to be on that side of the period.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top