In a real unit test, where there is more or less coupling between the classes we are testing, we can use Mockito. The Mockito library can Mock objects instead of the real ones we rely on, so we can avoid external influences. Test only this class to get more accurate results. Of course, it does more than that, for example TDD (Test Driven Development) is also a highlight, which I’ll explain in more detail below.

1. Mockito is introduced

Add dependencies in the build file when using.

Dependencies {testCompile "org.mockito:mockito-core:2.11.0"}Copy the code

Four mocks

  • Common method:
public class MockitoTest { @Test public void testIsNotNull(){ Person mPerson = mock(Person.class); //<-- Use the mock method assertNotNull(mPerson); }}Copy the code
  • Annotation method:
Public class MockitoAnnotationsTest {@mock //<-- annotate Person mPerson with @mock; @Before public void setup(){ MockitoAnnotations.initMocks(this); } @test public void testIsNotNull(){assertNotNull(mPerson); }}Copy the code
  • The runner method:
@ RunWith (MockitoJUnitRunner. Class) / / < - using MockitoJUnitRunner public class MockitoJUnitRunnerTest {@ Mock / / < - using the @ Mock annotation Person mPerson; @Test public void testIsNotNull(){ assertNotNull(mPerson); }}Copy the code
  • MockitoRule method
Public class MockitoRuleTest {@mock //<-- use @mock for Person mPerson; @rule public MockitoRule MockitoRule = mockitojunit.rule (); @Test public void testIsNotNull(){ assertNotNull(mPerson); }}Copy the code

The latter two methods are implemented in combination with the JUnit framework, which is detailed in my article: Using the JUnit Framework. The four methods are used according to personal habits, and I personally recommend the last one.

2. Common piling methods

Since all non-void methods on the Mock object will return the default value, int methods will return 0, object methods will return null, and void methods will do nothing. Piling, as the name implies, is to perform operations on the objects we Mock, such as providing the return value of the Mock.

The method name Methods described
thenReturn(T value) Sets the value to return
ThenThrow (Throwable… throwables) Sets the exception to be thrown
thenAnswer(Answer<? > answer) Intercept the results
doReturn(Object toBeReturned) Set the value to return in advance
DoThrow (Throwable… toBeThrown) Set the exception to throw in advance
doAnswer(Answer answer) Intercept the results in advance
doCallRealMethod() The actual implementation of calling a method
doNothing() Set the void method to do nothing

The figure above is a simple example where the code semantics are clear: when a method is executed, it returns what result. Of course, if we didn’t pile, the print would be null and 0.

DoReturn (" small "). The when (mPerson). GetName (); System.out.println(mperson.getName ());Copy the code

If a piling method such as doReturn is used, the semantics are: what result is returned, when what method is executed. The difference between the two is the familiar “while” and “do while”. This type of method is mainly for situations where you can’t use a method like thenReturn (such as void), and thenReturn is better for readability.

Examples of the thenAnswer method:

public String eat(String food){
        return food;
}Copy the code

The eat method is simple. We use thenAnswer to get what we ate and reprocess the returned results.

3. Common verification methods

All of this is a state test, but if you don’t care about the return result, you care about whether the method was called with the right arguments, then you should use validation methods. Conceptually, this is a “behavior test” as opposed to a state test.

Verify (T mock) Verifies that some behavior has occurred.

The method name Methods described
after(long millis) Validation is performed after a given time
timeout(long millis) Verify that method execution times out
atLeast(int minNumberOfInvocations) Perform at least n validations
atMost(int maxNumberOfInvocations) Perform at most n validations
description(String description) The output when the verification fails
times(int wantedNumberOfInvocations) Verify the number of times the method was called
never() Verify that the interaction did not occur, equal to times(0)
only() The validation method is only called once, which equals times(1)

Use the following code:

@Test public void testPersonVerifyAfter(){ when(mPerson.getAge()).thenReturn(18); System.out.println(mperson.getage ()); System.out.println(System.currentTimeMillis()); verify(mPerson, after(1000)).getAge(); System.out.println(System.currentTimeMillis()); verify(mPerson, atLeast(2)).getAge(); } @Test public void testPersonVerifyAtLeast(){ mPerson.getAge(); mPerson.getAge(); Verify (mPerson, atLeast(2)).getage (); } @Test public void testPersonVerifyAtMost(){ mPerson.getAge(); Verify (mPerson, atMost(2)).getage (); } @Test public void testPersonVerifyTimes(){ mPerson.getAge(); mPerson.getAge(); Verify (mPerson, times(2)).getage (); } @Test public void testPersonVerifyTimes(){ mPerson.getAge(); mPerson.getAge(); Verify (mPerson, timeout(100).times(2)).getage (); // Verify (mPerson, timeout(100).getage (); }Copy the code

4. Common parameter matchers

The method name Methods described
anyObject() Match any object
any(Class<T> type) With anyObject ()
any() With anyObject ()
anyBoolean() Matches any Boolean and non-empty Boolean
anyByte() Matches any byte and non-empty byte
anyCollection() Matches any non-empty Collection
anyDouble() Matches any double and non-empty double
anyFloat() Matches any float and non-empty float
anyInt() Matches any int and non-empty Integer
anyList() Matches any non-empty List
anyLong() Matches any long and non-empty long
anyMap() Matches any non-empty Map
anyString() Matches any non-empty String
contains(String substring) The argument contains the given substring string
argThat(ArgumentMatcher <T> matcher) Create a custom parameter matching pattern

Example code:

@test public void testPersonAny(){when(mperson.eat (any(string.class))).thenReturn(" rice "); / / or / / when (mPerson. Eat (anyString ())). ThenReturn (" rice "); System.out.println(mperson.eat (" noodle ")); } @test public void testPersonContains(){when(mperson.eat (contains(" face "))).thenreturn (" face "); System.out.println(mperson.eat (" noodles ")); } @test public void testPersonArgThat(){// Output noodles when input is an even number of characters. when(mPerson.eat(argThat(new ArgumentMatcher<String>() { @Override public boolean matches(String argument) { return argument.length() % 2 == 0; }})).thenreturn (" noodle "); System.out.println(mperson.eat ("1234")); }Copy the code

5. Other methods

The method name Methods described
Reset (T… mocks) Reset the Mock
spy(Class<T> classToSpy) Implementation calls the implementation of the real object
InOrder (Object… mocks) Verify execution order
@ InjectMocks annotations Automatically inject mock objects into the object under test (more on this later)

A Spy is created just like a mock, using the following example:

public class MockitoSpyTest { @Spy Person mPerson; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Test public void testIsNotNull(){ assertNotNull(mPerson); } @test public void testPersonSpy(){// output 11 system.out.print (mPerson.getage ()); }}Copy the code

InOrder uses code and test results:

2. Other

Mockito framework does not support mock anonymous classes, final classes, static methods, and private methods. The PowerMock framework solves these problems. I’ll talk about PowerMock in the next article. All of this code has been uploaded to Github. Hope you can give more support!

Reference 3.

  • Mockito Chinese documentation

  • JUnit + Mockito unit tests