path | title |
---|---|
/learnings/java_junit_mockito |
Learnings: Java: jUnit: Mockito |
- >
- >
- Syntax Examples
Mockito.mock
information:- Easy @Mock Annotation
- Dealing with methods that return null
- methods where we don't care what the passed parameter is
- Mocking a class where you want all methods to themselves return mocks
- Overriding implementation of specific methods
- Verifying mock methods called
- Overriding implementation of specific method with custom code
- >
- must implement interface or subclass and override required methods of interface/class
Stubs are useful when we want to control the behavior of the replaced dependencies. Mocks are useful when we want to control the behavior of the replaced dependencies and verify the interactions that happen between the system under test and the mock in question. Fakes are useful when we want to replace a problematic dependency with a test double that acts like the real thing. In other words, we don’t want to configure the response that is returned when a method of our test double is invoked and we don’t want to verify the interactions between the system under test and our test double.
Because we cannot verify that an interaction happened between the system under test and a stub, we should use stubs in situations where we don’t have to verify that the system under test actually invoked a method of a stub.
TOTALLY FAKE OBJECTS
Because we can verify that an interaction happened between the system under test and a mock, we should use mocks in situations where we want to verify that the system under test actually invoked a method of our mock object.
CAN SPY ON REAL OBJECTS!!!!
First, we need to verify the interactions between the system under test and our test double, and we don’t know how many times the target method is invoked or what values should be passed as method parameters. Because we cannot specify our expectations and verify interactions by using a mock object, our only option is to use a spy.
Overview:
- Has old Given/When syntax
- AND new BDD like syntax
- Mockito provides a custom test runner that would create our mocks for us with annotations, but ehhhh.... custom test runner = not ideal
Limitations:
- can not mock private methods??
- can not mock final??
- can not mock static methods??
- anon inner classes
PowerMockito for these????
Good reference on Mockito: https://dzone.com/refcardz/mockito
Old And Busted:
when( instance.method() ).thenReturn(1)
New Hotness (BDD) BDDMockito:
given( instance.method() ).willReturn(1)
doNothing( ).given( instance ).voidMethod()
- by default returns null for all methods implemented by that class
- can provide a default answer for all(????) methods called. Not a great idea, but....
public class ArkShip {
@Mock Hyperdrive engine;
}
NOTES:
- When using this annotation need
MockitoJUnitRunner
as the@RunWith
annotation over the test class - OR manually call
MockitoAnnotations.initMocks(this)
to inject the dependancies.
doNothing().when( myMock ).myMethod( ... )
doAnswer( invocation -> this.count++).when( mock ).myMethod( ... );
when( myMock.myMethod( any( String.class ) ) ).thenReturn( 42 );
In case where you're mocking out a fluent API:
myThing.someMethod(0).increment()
In test code:
Spaceship destiny = mock( Spaceship,
Example that shows how deep stub works:
Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
// note that we're stubbing a chain of methods here: getBar().getName()
when(mock.getBar().getName()).thenReturn("deep");
// note that we're chaining method calls: getBar().getName()
assertEquals("deep", mock.getBar().getName());
import org.junit.Before;
import org.junit.Test;
import static com.testwithspring.task.TestDoubles.stub;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
class WhateverTest {
private TaskRepository t;
@Before
public void createStub() {
t = stub(TaskRepository.class);
}
@Test
public void shouldReturnValue() {
given(t.count()).willReturn(1);
// or make it throw an exception
given(t.findById(1L)).willThrow(new NotFoundException());
assertThat( t.count() ).isEqualByComparingTo(1);
}
}
Can also use willAnswer
API to provide custom implementations with a lambda.
Use spy
: this will only mock the methods you tell it about.
ArrayList<String> s = org.mockito.Mockito.spy( new ArrayList<String>() );
org.mockito.Mockito.doReturn( 42 ).when( s ).size();
import org.junit.Before;
import org.junit.Test;
import static com.testwithspring.task.TestDoubles.stub;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
class WhateverTest {
private TaskRepository t;
@Before
public void createStub() {
t = stub(TaskRepository.class);
}
@Test
public void shouldReturnValue() {
verify(t).countMethod()
}
}
NOTE: if you're doing this with a stub/mock you don't have to set up a specific when
clause just to verify some function will be called. (My default methods called on mocks/stubs this way return null).
May need to use special maven dep:
<dependency>
<groupId>info.solidsoft.mockito</groupId>
<artifactId>mockito-java8</artifactId>
<version>0.3.1</version>
<scope>test</scope>
</dependency>
given(repository.count(1L)).willAnswer(invocation -> {
return 42;
} );
whenever( someInstance.someMethod(parameterNameOne = mockitoParameterMatcher)).thenReturn(somePrimative)
(don't use when Mockito function as that's a keyword in Kotlin. You can, but encase it with backticks then it looks awkward)
verify(someInstance).someMethod(parameterNameOne = expectedValue)
are you using your someInstance
is a mock<SomeClass>()
, or might it be a SomeClass()
aka not actually a mock object?
use anyOrNull
matcher.
verify(someInstance).someMethod(parameterName = anyOrNull)
use check
closure / (Java8 Functional Predicate ie bool Predicate<T>
)
verify(someInstance).someMethod(check { argumentOne ->
argumentOne shouldBe "foo"
}, check { argumentTwo -> argumentTwo shouldBe "bar"})