Mockito
This article may be too technical for most readers to understand.(February 2010) |
In software development, there is a persistent problem of ensuring that objects perform the behaviors that are expected of them. One approach is to create a testing framework that actually exercises each of those behaviors and verifies that it performs as expected, even after it is changed. However, the requirement to create an entire testing framework is often an onerous task that requires as much effort as writing the original objects that were supposed to be tested. For that reason, developers have created "mock" testing frameworks. These effectively "fake" some external dependencies so that the object being tested has a consistent interaction with its outside dependencies. Mockito is an open-source testing framework that intends to streamline the delivery of these external dependencies that are not subjects of the test. Mockito is an open source testing framework for Java released under the MIT License.[1][2][3] The framework allows the creation of Test Double objects (called "Mock Objects") in automated unit tests for the purpose of Test-driven Development (TDD) or Behavior Driven Development (BDD).
Distinguishing features
Mockito distinguishes itself from other mocking frameworks by allowing developers to verify the behavior of the system under test (SUT) without establishing expectations beforehand.[4] One of the criticisms of mock objects is that there is a tighter coupling of the test code to the system under test.[5] Since Mockito attempts to eliminate the expect-run-verify pattern[6] by removing the specification of expectations, the coupling is reduced or minimized. The result of this distinguishing feature is simpler test code that should be easier to read and modify.
Origins
Szczepan Faber started the Mockito project after finding existing mock object frameworks too complex and difficult to work with. Faber began by expanding on the syntax and functionality of Easy Mock, but eventually rewriting most of Mockito.[7] Faber's goal was to create a new framework that was easier to work with and provided better results. Early versions of Mockito project found use by the Guardian project in London in early 2008.[8]
Usage
Mockito has a growing user-base[9] as well as finding use in other open source projects.[10]
Example
First of all consider some simple "decoupled" Hello world application, so then we will be able to test some of its parts, using mock objects for other parts.
package org.examples;
import java.io.IOException;
public class HelloApplication {
public static interface HelloSource {
String getHello(String subject);
String getIntroduction(String actor);
}
public static class HelloSourceImpl implements HelloSource {
private String hello;
private String column;
public HelloSourceImpl(String hello, String column) {
this.hello = hello;
this.column = column;
}
public String getHello(String subject) {
return hello + " " + subject;
}
public String getIntroduction(String actor) {
return actor+column;
}
}
public static interface HelloAction {
void sayHello(String actor, String subject) throws IOException;
}
public static class HelloActionImpl implements HelloAction {
private HelloSource helloSource;
private Appendable helloWriter;
public HelloActionImpl(HelloSource helloSource, Appendable helloWriter) {
super();
this.helloSource = helloSource;
this.helloWriter = helloWriter;
}
public void sayHello(String actor, String subject) throws IOException {
helloWriter.append(helloSource.getIntroduction(actor)).append(helloSource.getHello(subject));
}
}
public static void main(String... args) throws IOException {
new HelloActionImpl(new HelloSourceImpl("hello", ": "), System.out).sayHello("application", "world");
}
}
The result of HelloApplication launching will be the following:
application: hello world
Unit test for HelloAction component may look like this:
package org.examples;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.examples.HelloApplication.HelloAction;
import org.examples.HelloApplication.HelloActionImpl;
import org.examples.HelloApplication.HelloSource;
public class HelloActionUnitTest {
HelloSource helloSourceMock;
Appendable helloWriterMock;
HelloAction helloAction;
@Before
public void setUp() {
helloSourceMock = mock(HelloSource.class);
helloWriterMock = mock(Appendable.class);
helloAction = new HelloActionImpl(helloSourceMock, helloWriterMock);
}
@Test
public void testSayHello() throws Exception {
when(helloWriterMock.append(any(String.class))).thenReturn(helloWriterMock);
when(helloSourceMock.getIntroduction(eq("unitTest"))).thenReturn("unitTest : ");
when(helloSourceMock.getHello(eq("world"))).thenReturn("hi world");
helloAction.sayHello("unitTest", "world");
verify(helloSourceMock).getIntroduction(eq("unitTest"));
verify(helloSourceMock).getHello(eq("world"));
verify(helloWriterMock, times(2)).append(any(String.class));
verify(helloWriterMock, times(1)).append(eq("unitTest : "));
verify(helloWriterMock, times(1)).append(eq("hi world"));
}
}
As you can see, it uses mock objects for HelloSource and Appendable interfaces, and implicitly assumes next "use case":
unitTest : hi world
Integration test code for testing HelloAction wired together with HelloSource may look like the following:
package org.examples;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.examples.HelloApplication.HelloAction;
import org.examples.HelloApplication.HelloActionImpl;
import org.examples.HelloApplication.HelloSource;
import org.examples.HelloApplication.HelloSourceImpl;
public class HelloActionIntegrationTest {
HelloAction helloAction;
HelloSource helloSource;
Appendable helloWriterMock;
@Before
public void setUp() {
helloSource = new HelloSourceImpl("welcome", " says ");
helloWriterMock = mock(Appendable.class);
helloAction = new HelloActionImpl(helloSource, helloWriterMock);
}
@Test
public void testSayHello() throws Exception {
when(helloWriterMock.append(any(String.class))).thenReturn(helloWriterMock);
helloAction.sayHello("integrationTest", "universe");
verify(helloWriterMock, times(2)).append(any(String.class));
verify(helloWriterMock, times(1)).append(eq("integrationTest says "));
verify(helloWriterMock, times(1)).append(eq("welcome universe"));
}
}
It uses mock object only in place of Appendable interfaces, and uses the real implementations for other (HelloAction and HelloSource) interfaces, and implicitly assumes next "use case":
integrationTest says welcome universe
Finally, as can be seen from the import statements of HelloActionUnitTest and HelloActionIntegrationTest classes, it is necessary to put some Mockito jars and Junit jars in your class path to be able compile and run the test classes.
See also
- Behavior driven development
- Mock object
- List of unit testing frameworks
- Software testing
- Unit testing
References
- ^ Collins, Alex (2010). "5 minute Mockito". DZone.
{{cite web}}
:|access-date=
requires|url=
(help); Missing or empty|url=
(help) - ^ "Mockito in six easy examples". 2009. Retrieved 2012-10-05.
- ^ "What's the best mock framework for Java?". Retrieved 2010-12-29.
- ^ "Features and Motivations". Retrieved 2010-12-29.
- ^ Fowler, Martin (2007). "Mocks Aren't Stubs". Retrieved 2010-12-29.
- ^ Faber, Szczepan. "Death Wish". Retrieved 2010-12-29.
- ^ Faber, Szczepan. "Mockito". Retrieved 2010-12-29.
- ^ "Mockito Home Page". Retrieved 2010-12-29.
- ^ "Mockito User Base". Retrieved 2010-12-29.
- ^ "Mockito in Use". Retrieved 2010-12-29.