Reputation: 2830
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
?
Upvotes: 3
Views: 2892
Reputation: 11051
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.
Upvotes: -1
Reputation: 2830
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?
Upvotes: 2
Reputation: 21258
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.
Upvotes: 2