Skip to content

Instantly share code, notes, and snippets.

@kbrv37
Last active October 28, 2020 15:44
Show Gist options
  • Save kbrv37/b7b68432f32630a74ce9e936a9d49745 to your computer and use it in GitHub Desktop.
Save kbrv37/b7b68432f32630a74ce9e936a9d49745 to your computer and use it in GitHub Desktop.

Mockito Cheatsheet

Mocking methods that return values

  1. Step one is to mock your class (or Interface)

TestClass mockedObject = mock(TestClass.class);

⚠️ By default, all methods of a mock return “uninitialized” or “empty” values, e.g., zeros for numeric types (both primitive and boxed), false for booleans, and nulls for most other types.

Now, you can specify what to return when the method is called. Mockito supports two different ways:

when-thenReturn

2a. Now that the mock is created, you can mock the object

when(mockedObject.method()).thenReturn(WhatYouWantToReturnHere);

doReturn-when

2b. Now that the mock is created, you can mock the object

doReturn(WhatYouWantToReturnHere).when(mockedObject).method());

⚠️ doReturn has no type checking in the compile time. Read more about the differences between when-thenReturn and doReturn-when at the link below

http://sangsoonam.github.io/2019/02/04/mockito-doreturn-vs-thenreturn.html

Mocking void methods

These verify methods are generally used to check/unit test the "side-effects" of void return type methods.

Verify

  1. Check if some method was called

verify(mockedcObject).method(methodParameters);

  1. Check if some method is never called

verify(mockedObject, never()).method(methodParameters);

  1. Check the number of times a method is called (N = number of times you want to verify method called)

verify(mockedObject, times(N)).method(methodParameters);

Argument Matchers

You can use argument matchers when you need flexible verification or stubbing. Use it when you don't want to hardcode method arguments and need the mocked method to respond to a wider range of values or beforehand unknown values.

Some common argument matchers are:

  • anyBoolean()
  • anyInt()
  • anyString()
  • any() (for any Objects)

Example:

when(mockedList.get(anyInt())).thenReturn("element");

Mocking exceptions

Sometimes you want to write a unit test for verify a method throws an exception for certain edge cases. The typical structure is:

@Test(expected=MyException.class)
public void testingMethodThrowsException() {
    when(mockedObject.method()).thenThrow(new MyException("my exception message here"));
   }

You can test this with a common exception like NullPointerException.class

Argument Captors

Used for checking the values passed to a mocked method.

  1. Declare Argument Captor (i.e. for capturing a String argument)

ArgumentCaptor<String> stringArgumentCaptor = ArgumentCaptor.forClass(String.class);

  1. Define Argument Captor on method

verify(mockedOjbect).method(stringArgumentCaptor.capture());

  1. Capture the argument

assertThat(stringArgumentCaptor.getValue(), is("ExpectedCapturedValue"));

Spys

Used when you want to override some logic, but want to retain all other functionality of a class. Code below would fail if just using standard mock for ArrayList because add() method would do nothing to the mocked object, and size() would return 0 even after adding. However, when using a Spy, it is not a mocked object but a real ArrayList and all other class logic/functionality is retained and thus calling add() on this ArrayList increases its size and the test passes.

// Using regular Mock. Test fails
List arrayListSpy = mock(ArrayList.class);
assertEquals(0 , arrayListSpy.size());
arrayListSpy.add("Dummy");
assertEquals(1, arrayListSpy.size()); // Returns 0

// Using Mockito Spys. Test passes
List arrayListSpy = spy(ArrayList.class);
assertEquals(0 , arrayListSpy.size());
arrayListSpy.add("Dummy");
assertEquals(1, arrayListSpy.size()); // Returns 1

PowerMockito

You'll need PowerMockito for mocking static or private methods. All repos will already have it declared as a dependency, so you can start using it right away.

Mocking private methods

There are more overloaded variations of Whitebox.invokeMethod(), but this is one commonly used example:

Whitebox.invokeMethod(mockedObject, "privateMethodName", method arguments...);

Mocking static methods

  1. Specify the Runner and Prepare the class for mocking. Add the annotations below to the Unit Test Class you created, above your class declaration:
@PrepareForTest({ ClassThatContainsStaticMethod.class })
@RunWith(PowerMockRunner.class)

public class MyUnitTest {
   // blah
   }
  1. Mock your class that contains static method using PowerMockito API

ClassThatContainsStaticMethod mockedObject = PowerMockito.mockStatic(ClassThatContainsStaticMethod.class);

  1. Mock the object as before

when(ClassThatContainsStaticMethod.staticMethod()).thenReturn(WhatYouWantToReturnHere);

Mocking constructor

  1. Prepare class that makes use of constructor
@PrepareForTest({ ClassThatIsUsingConstructor.class })
@RunWith(PowerMockRunner.class)

public class MyUnitTest {
   // blah
   }

PowerMockito.whenNew(ClassOfConstructor.class).withAnyArguments().thenReturn(mockClassOfConstructor);

Extras

Verify Static Void Method

@PrepareForTest(DAO.class)
    @RunWith(PowerMockRunner.class)
    public class VerifyTest {
         @Test
         public void verifyTest() {
             // Object under test
             UnderTest obj = new UnderTest();
     
             // Mock
             PowerMockito.mockStatic(DAO.class);
     
             // Execute method under test
             obj.foo();
     
             // Test; default to verifying a single call
             PowerMockito.verifyStatic();
             DAO.executeSQL();
         }
    }

Mocking Log

// prev: Mockito, PowerMockito, Whitebox, etc. imports
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestClass{
  private static Logger logger = mock(Logger.class);
  
  @BeforeClass
  public static void init(){
    Whitebox.setInternalState(ClassImTesting.class, "log", logger);
  }
  
  @AfterClass
  public static void uninit(){
    Whitebox.setInternalState(ClassImTesting.class, "log", LoggerFactory.getLogger(ClassImTesting.class));
  }
  
  @Before
  public void setUp(){
    Mockito.reset(logger);
  }
  
  @Test
  public void methodToTest(){
    ClassImTesting.methodImTesting();
    Mockito.verify(logger, Mockito.times(1)).error("the error");
    Mockito.verify(logger, Mockito.times(1)).info(anyString()); // etc.
  }
  
  // for test that's expected to throw an exception:
  @Test
  public void throwExceptionTest(){
    try{
      methodImTesting();
    }
    catch(Exception e){
      assertEquals("expected message", e.getMessage());
    }
    Mockito.verify(logger, Mockito.times(1)).warn(anyString(), anyInt(), anyInt());
  }
}

Bypass Thread.sleep()

PowerMockito.mockStatic(Thread.class);
doNothing().when(Thread.class, "sleep", anyLong());

Set state of static field

Whitebox.setInternalState(Foo.class, "FIELD_NAME", "value");

Common Issues

  1. java.lang.NullPointerException

Usually means something didn't get mocked in the method you're trying test

  1. org.mockito.exceptions.misusing.InvalidUseOfMatchersException

When you use an argument matcher for one of the arguments, all the other arguments must also use an argument matcher, so something like:

when(mockedObject.method(anyString(), "Test1234").thenReturn(WhatYouWantToReturnHere);

would throw this exception because the method has an argument matcher as the first parameter, however uses a String type for the second parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment