Show navigation Hide navigation

Building Local Unit Tests

Dependencies and Prerequisites

  • Android Plug-in for Gradle 1.1.0 or higher

This lesson teaches you to

  1. Set Up Your Testing Environment
  2. Create a Local Unit Test Class
  3. Run Local Unit Tests

Try it out

If your unit test has no dependencies or only has simple dependencies on Android, you should run your test on a local development machine. This testing approach is efficient because it helps you avoid the overhead of loading the target app and unit test code onto a physical device or emulator every time your test is run. Consequently, the execution time for running your unit test is greatly reduced. With this approach, you normally use a mocking framework, like Mockito, to fulfill any dependency relationships.

Android Plug-in for Gradle version 1.1.0 and higher allows you to create a source directory (src/test/java) in your project to store JUnit tests that you want to run on a local machine. This feature improves your project organization by letting you group your unit tests together into a single source set. You can run the tests from Android Studio or the command-line, and the plugin executes them on the local Java Virtual Machine (JVM) on your development machine.

Set Up Your Testing Environment

Before building local unit tests, you must:

  • Set up your project structure. In your Gradle project, the source code for the target app that you want to test is typically placed under the app/src/main/java folder. The source code for your local unit tests must be placed under the app/src/test/java folder. To learn more about setting up your project directory, see Run Local Unit Tests and Managing Projects.
  • Specify your Android testing dependencies. In order to use JUnit 4 and Mockito with your local unit tests, specify the following libraries in the build.gradle file of your Android app module:
    dependencies {
        // Unit testing dependencies
        testCompile 'junit:junit:4.12'
        // Set this dependency if you want to use Mockito
        testCompile 'org.mockito:mockito-core:1.10.19'
        // Set this dependency if you want to use Hamcrest matching
        androidTestCompile 'org.hamcrest:hamcrest-library:1.1'
    }
    

Create a Local Unit Test Class

Your local unit test class should be written as a JUnit 4 test class. JUnit is the most popular and widely-used unit testing framework for Java. The latest version of this framework, JUnit 4, allows you to write tests in a cleaner and more flexible way than its predecessor versions. Unlike the previous approach to Android unit testing based on JUnit 3, with JUnit 4, you do not need to extend the junit.framework.TestCase class. You also do not need to prefix your test method name with the ‘test’ keyword, or use any classes in the junit.framework or junit.extensions package.

To create a basic JUnit 4 test class, create a Java class that contains one or more test methods. A test method begins with the @Test annotation and contains the code to exercise and verify a single functionality in the component that you want to test.

The following example shows how you might implement a local unit test class. The test method emailValidator_CorrectEmailSimple_ReturnsTrue verifies that the isValidEmail() method in the app under test returns the correct result.

import org.junit.Test;
import java.util.regex.Pattern;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class EmailValidatorTest {

    @Test
    public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
        assertThat(EmailValidator.isValidEmail("name@email.com"), is(true));
    }
    ...
}

To test that components in your app return the expected results, use the junit.Assert methods to perform validation checks (or assertions) to compare the state of the component under test against some expected value. To make tests more readable, you can use Hamcrest matchers (such as the is() and equalTo() methods) to match the returned result against the expected result.

In your JUnit 4 test class, you can use annotations to call out sections in your test code for special processing, such as:

  • @Before: Use this annotation to specify a block of code with test setup operations. This code block will be invoked before each test. You can have multiple @Before methods but the order which these methods are called is not fixed.
  • @After: This annotation specifies a block of code with test tear-down operations. This code block will be called after every test method. You can define multiple @After operations in your test code. Use this annotation to release any resources from memory.
  • @Test: Use this annotation to mark a test method. A single test class can contain multiple test methods, each prefixed with this annotation.
  • @BeforeClass: Use this annotation to specify static methods to be invoked only once per test class. This testing step is useful for expensive operations such as connecting to a database.
  • @AfterClass: Use this annotation to specify static methods to be invoked only after all tests in the class have been run. This testing step is useful for releasing any resources allocated in the @BeforeClass block.
  • @Test(timeout=<milliseconds>): Specifies a timeout period for the test. If the test starts but does not complete within the given timeout period, it automatically fails. You must specify the timeout period in milliseconds, for example: @Test(timeout=5000).

Mocking Android dependencies

By default, the Android Plug-in for Gradle executes your local unit tests against a modified version of the android.jar library, which does not contain any actual code. Instead, method calls to Android classes from your unit test throw an exception.

You can use a mocking framework to stub out external dependencies in your code, to easily test that your component interacts with a dependency in an expected way. By substituting Android dependencies with mock objects, you can isolate your unit test from the rest of the Android system while verifying that the correct methods in those dependencies are called. The Mockito mocking framework for Java (version 1.9.5 and higher) offers compatibility with Android unit testing. With Mockito, you can configure mock objects to return some specific value when invoked.

To add a mock object to your local unit test using this framework, follow this programming model:

  1. Include the Mockito library dependency in your build.gradle file, as described in Set Up Your Testing Environment.
  2. At the beginning of your unit test class definition, add the @RunWith(MockitoJUnitRunner.class) annotation. This annotation tells the Mockito test runner to validate that your usage of the framework is correct and simplifies the initialization of your mock objects.
  3. To create a mock object for an Android dependency, add the @Mock annotation before the field declaration.
  4. To stub the behavior of the dependency, you can specify a condition and return value when the condition is met by using the when() and thenReturn() methods.

The following example shows how you might create a unit test that uses a mock Context object.

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import android.content.SharedPreferences;

@RunWith(MockitoJUnitRunner.class)
public class UnitTestSample {

    private static final String FAKE_STRING = "HELLO WORLD";

    @Mock
    Context mMockContext;

    @Test
    public void readStringFromContext_LocalizedString() {
        // Given a mocked Context injected into the object under test...
        when(mMockContext.getString(R.string.hello_word))
                .thenReturn(FAKE_STRING);
        ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);

        // ...when the string is returned from the object under test...
        String result = myObjectUnderTest.getHelloWorldString();

        // ...then the result should be the expected one.
        assertThat(result, is(FAKE_STRING));
    }
}

To learn more about using the Mockito framework, see the Mockito API reference and the SharedPreferencesHelperTest class in the sample code.

Run Local Unit Tests

The Android Plug-in for Gradle provides a default directory (src/test/java) for you to store unit test classes that you want to run on a local JVM. The plug-in compiles the test code in that directory and then executes the test app locally using the default test runner class.

As with production code, you can create unit tests for a specific flavor or build type. You should keep unit tests in a test source tree location that corresponds to your production source tree, such as:

Path to Production Class Path to Local Unit Test Class
src/main/java/Foo.java src/test/java/FooTest.java
src/debug/java/Foo.java src/testDebug/java/FooTest.java
src/myFlavor/java/Foo.java src/testMyFlavor/java/FooTest.java

Running local unit tests from Android Studio

To run local unit tests in your Gradle project from Android Studio:

  1. In the Project window, right click on the project and synchronize your project.
  2. Open the Build Variants window by clicking the left-hand tab, then change the test artifact to Unit Tests.
  3. In the Project window, drill down to your unit test class or method, then right-click and run it.

Android Studio displays the results of the unit test execution in the Run window.

Running local unit tests from the command-line

To run local unit tests in your Gradle project from the command-line, call the test task command with the --continue option.

./gradlew test --continue

If there are failing tests, the command will display links to HTML reports (one per build variant). You can find the generated HTML test result reports in the <path_to_your_project>/app/build/reports/tests/ directory, and the corresponding XML files in the <path_to_your_project>/app/build/test-results/ directory.