Mockito is a Java-based framework for creating mock objects. It allows developpers to create mocks based on classes or interfaces, specify behaviour and return values for methods, and verify interactions.
This article introduces the use of Mockito in JUnit tests, to test object interactions, and shows mock creations, method stubbing, and verification of interactions.
Mocks can be created in 2 ways :
And that's it! Mock are quickly created and provide default comportement, methods return null, empty collections, false, or 0 depending on the return type of the method.
You can mock interfaces (nice for TDD and low-coupling) and concrete classes too.
Mockito also provides a JUnit test runner, that handles the @Mock initialization.
Now that the mocks are created, we can specify stub methods.
The stubs are created using "when" and "thenReturn" methods. Stubs are specified with different arguments that can be hard coded (if the argument is well-known as in the moveForward(0) exemple), or with argument matchers ( as in moveForward(anyInt()) ). Mockito comes with built-in argument matchers (anyInt(), anyBoolean(), anyString()... ), and allows creation of custom matchers. Method stubs can also throw exceptions.
Now that we have a mocked Robot, we can test our RemoteControl. The following code creates a RemoteControl and attaches it to a Robot, then verifies that the methods of the Robot are correctly called.
The verify method takes 2 arguments : a mock, and a number of invocations.
Here, verify checks that the moveForward() method has been called on the robotMock with the parameter 1, and only once ( times(1) is an optionnal parameter ), and that the robot was told to turn to the west direction. The verifyNoMoreInteractions() method checks that no other method has been called on the mock.
The second argument of verify() can be an exact number ( times(1), times(3) ... ), never(), or atLeast(2), atMost(4)...
Mockito provides a simple way to write mocks, specify their behaviour with stubs, and then verify the interactions between objects. It can be very useful to write isolation tests, and to develop in TDD (Test Driven Development). You can concentrate on one class of the application without having to develop all its dependencies (by the way, it encourages low-coupling, great!).
This article introduces the use of Mockito in JUnit tests, to test object interactions, and shows mock creations, method stubbing, and verification of interactions.
Creation of mocks
Mocks can be created in 2 ways :
import org.mockito.*;
import static org.mockito.Mockito.*;
public class TestRobotRemoteControl{
@Mock
private Robot robotMock;
@Before
public void setUp(){
// first way
this.robotMock = mock( Robot.class );
/* second way, creates mocks for all
the @Mock annotated attributes of the class */
MockitoAnnotations.initMocks( this );
}
}
And that's it! Mock are quickly created and provide default comportement, methods return null, empty collections, false, or 0 depending on the return type of the method.
You can mock interfaces (nice for TDD and low-coupling) and concrete classes too.
Mockito also provides a JUnit test runner, that handles the @Mock initialization.
@RunWith(MockitoJUnit44Runner.class)
public class TestRobotRemoteControl{
@Mock
private Robot robotMock;
}
Stubbing
Now that the mocks are created, we can specify stub methods.
@Before
public void setUp(){
// getDirection() will return Direction.NORTH
when(robotMock1.getDirection()).thenReturn(Direction.NORTH);
// moveForward() takes an int in parameter and returns true
when(robotMock1.moveForward(anyInt())).thenReturn(true);
// when moveForward() is called with a 0 parameter,
// it returns false because the robot doesn't move...
when(robotMock1.moveForward(0)).thenReturn(false);
// turnTo takes any Direction in parameter
when( robotMock1.turnTo( isA(Direction.class) ) )
.thenReturn(true);
doThrow( new IllegalArgumentException() )
.when( robotMock ).turnTo( null );
}
The stubs are created using "when" and "thenReturn" methods. Stubs are specified with different arguments that can be hard coded (if the argument is well-known as in the moveForward(0) exemple), or with argument matchers ( as in moveForward(anyInt()) ). Mockito comes with built-in argument matchers (anyInt(), anyBoolean(), anyString()... ), and allows creation of custom matchers. Method stubs can also throw exceptions.
Verifying interactions
Now that we have a mocked Robot, we can test our RemoteControl. The following code creates a RemoteControl and attaches it to a Robot, then verifies that the methods of the Robot are correctly called.
@Test
public void testRemote(){
RemoteControl remote = new RemoteControl();
remote.setControlling(robotMock);
// This should make the robot move 1 step
remote.pressForward();
// This should make the robot turn to WEST direction
// because it was facing NORTH
remote.pressTurnLeft();
// verifications
verify( robotMock, times(1)).moveForward(1);
verify( robotMock ).turnTo( Direction.WEST );
verifyNoMoreInteractions(robotMock1);
}
The verify method takes 2 arguments : a mock, and a number of invocations.
Here, verify checks that the moveForward() method has been called on the robotMock with the parameter 1, and only once ( times(1) is an optionnal parameter ), and that the robot was told to turn to the west direction. The verifyNoMoreInteractions() method checks that no other method has been called on the mock.
The second argument of verify() can be an exact number ( times(1), times(3) ... ), never(), or atLeast(2), atMost(4)...
Conclusion
Mockito provides a simple way to write mocks, specify their behaviour with stubs, and then verify the interactions between objects. It can be very useful to write isolation tests, and to develop in TDD (Test Driven Development). You can concentrate on one class of the application without having to develop all its dependencies (by the way, it encourages low-coupling, great!).
1 comments :
Thanks
Post a Comment