Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up Mockito to mock class for Android unit test

If I make a simple test case like

@Test
public void myTest() throws Exception {
    Spanned word = new SpannedString("Bird");
    int length = word.length();
}

an exception is thrown

java.lang.RuntimeException: Method length in android.text.SpannableStringInternal not mocked. See http://g.co/androidstudio/not-mocked for details.

This is explained in the link above as

The android.jar file that is used to run unit tests does not contain any actual code - that is provided by the Android system image on real devices. Instead, all methods throw exceptions (by default). This is to make sure your unit tests only test your code and do not depend on any particular behaviour of the Android platform (that you have not explicitly mocked e.g. using Mockito).

So how do you set up Mockito in an Android project in order to mock classes like this?

I want to learn, so I am going to add my answer below Q&A style.

like image 485
Suragch Avatar asked Jul 01 '17 09:07

Suragch


People also ask

Can Mockito mock a class?

Mockito mocking framework provides different ways to mock a class. Let's look at different methods through which we can mock a class and stub its behaviors.

How does Mockito work on Android?

In Mockito, we mock any class using @Mock annotation. By Mocking any class, we are creating an mock object of that speicifc class. In the above code, Operators is mocked to provide dependency for Calculator class. Here, to perform test we need to annotate the function with @Test.


1 Answers

It is not difficult to set up Mockito in your project. The steps are below.

1. Add the Mockito dependency

Assuming you are using the jcenter repository (the default in Android Studio), add the following line to the dependencies block of your app's build.gradle file:

testImplementation "org.mockito:mockito-core:2.8.47"

You can update the version number to whatever is the most recent Mockito version is.

It should look something like this:

dependencies {
    // ...
    testImplementation 'junit:junit:4.12'
    testImplementation "org.mockito:mockito-core:2.8.47"
}

2. Import Mockito into your test class

By importing a static class you can make the code more readable (ie, instead of calling Mockito.mock(), you can just use mock()).

import static org.mockito.Mockito.*;

3. Mock objects in your tests

You need to do three things to mock objects.

  1. Create a mock of the class using mock(TheClassName.class).
  2. Tell the mocked class what to return for any methods you need to call. You do this using when and thenReturn.
  3. Use the mocked methods in your tests.

Here is an example. A real test would probably use the mocked value as some sort of input for whatever is being tested.

public class MyTestClass {

    @Test
    public void myTest() throws Exception {
        // 1. create mock
        Spanned word = mock(SpannedString.class);

        // 2. tell the mock how to behave
        when(word.length()).thenReturn(4);

        // 3. use the mock
        assertEquals(4, word.length());
    }
}

Further study

There is a lot more to Mockito. See the following resources to continue your learning.

  • Mockito documentation
  • Unit tests with Mockito - Tutorial
  • Mockito on Android
  • Testing made sweet with a Mockito by Jeroen Mols (YouTube)

Or try this...

It is good to learn mocking because it is fast and isolates the code being tested. However, if you are testing some code that uses an Android API, it might be easier to just use an instrumentation test rather than a unit test. See this answer.

like image 160
Suragch Avatar answered Oct 03 '22 17:10

Suragch