| page.title=Building Local Unit Tests | |
| page.tags=testing,androidjunitrunner,junit,unit test,mock | |
| trainingnavtop=true | |
| @jd:body | |
| <!-- This is the training bar --> | |
| <div id="tb-wrapper"> | |
| <div id="tb"> | |
| <h2>This lesson teaches you to</h2> | |
| <ol> | |
| <li><a href="#setup">Set Up Your Testing Environment</a></li> | |
| <li><a href="#build">Create a Local Unit Test Class</a> | |
| <ol> | |
| <li><a href="#mocking-dependencies">Mock Android dependencies</a></li> | |
| </ol> | |
| </li> | |
| <li><a href="#run">Run Local Unit Tests</a></li> | |
| </ol> | |
| <h2>Try it out</h2> | |
| <ul> | |
| <li> | |
| <a href="https://github.com/googlesamples/android-testing/tree/master/unit/BasicSample" | |
| class="external-link">Local Unit Tests Code Samples</a></li> | |
| <li><a href="https://codelabs.developers.google.com/codelabs/android-testing/index.html?index=..%2F..%2Findex#0" | |
| class="external-link">Android Testing Codelab</a></li> | |
| </ul> | |
| </div> | |
| </div> | |
| <p>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 | |
| <a href="https://github.com/mockito/mockito" class="external-link">Mockito</a>, to fulfill any | |
| dependency relationships.</p> | |
| <h2 id="setup">Set Up Your Testing Environment</h2> | |
| <p>In your Android Studio project, you must store the source files for local | |
| unit tests at <code><var>module-name</var>/src/test/java/</code>. This directory | |
| already exists when you create a new project.</p> | |
| <p>You also need to configure the testing dependencies for your project to use | |
| the standard APIs provided by the JUnit 4 framework. If your test needs to | |
| interact with Android dependencies, include the <a href= | |
| "https://github.com/mockito/mockito" class="external-link">Mockito</a> library | |
| to simplify your local unit tests. To learn more about using mock objects in | |
| your local unit tests, see <a href= | |
| "{@docRoot}training/testing/unit-testing/local-unit-tests.html#mocking-dependencies"> | |
| Mocking Android dependencies</a>.</p> | |
| <p>In your app's top-level {@code build.gradle} file, you need to specify these | |
| libraries as dependencies:</p> | |
| <pre> | |
| dependencies { | |
| // Required -- JUnit 4 framework | |
| testCompile 'junit:junit:4.12' | |
| // Optional -- Mockito framework | |
| testCompile 'org.mockito:mockito-core:1.10.19' | |
| } | |
| </pre> | |
| <h2 id="build">Create a Local Unit Test Class</h2> | |
| <p>Your local unit test class should be written as a JUnit 4 test class. | |
| <a href="http://junit.org/" class="external-link">JUnit</a> 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 {@code junit.framework.TestCase} class. You also do not need to prefix your test method | |
| name with the {@code ‘test’} keyword, or use any classes in the {@code junit.framework} or | |
| {@code junit.extensions} package.</p> | |
| <p>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 {@code @Test} annotation and contains the code to exercise | |
| and verify a single functionality in the component that you want to test.</p> | |
| <p>The following example shows how you might implement a local unit test class. The test method | |
| {@code emailValidator_CorrectEmailSimple_ReturnsTrue} verifies that the {@code isValidEmail()} | |
| method in the app under test returns the correct result.</p> | |
| <pre> | |
| 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)); | |
| } | |
| ... | |
| } | |
| </pre> | |
| <p>To test that components in your app return the expected results, use the | |
| <a href="http://junit.org/javadoc/latest/org/junit/Assert.html" class="external-link"> | |
| junit.Assert</a> methods to perform validation checks (or <em>assertions</em>) to compare the state | |
| of the component under test against some expected value. To make tests more readable, you | |
| can use <a href="https://github.com/hamcrest" class="external-link"> | |
| Hamcrest matchers</a> (such as the {@code is()} and {@code equalTo()} methods) to match the | |
| returned result against the expected result.</p> | |
| <h3 id="mocking-dependencies">Mock Android dependencies</h3> | |
| <p>By default, the <a href= | |
| "{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for | |
| Gradle</a> executes your local unit tests against a modified version of the | |
| {@code android.jar} library, which does not contain any actual code. Instead, | |
| method calls to Android classes from your unit test throw an exception. This is | |
| to make sure you test only your code and do not depend on any | |
| particular behavior of the Android platform (that you have not explicitly | |
| mocked).</p> | |
| <p> | |
| 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 | |
| <a href="https://github.com/mockito/mockito" class="external-link">Mockito</a> 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.</p> | |
| <p>To add a mock object to your local unit test using this framework, follow this programming model: | |
| </p> | |
| <ol> | |
| <li> | |
| Include the Mockito library dependency in your {@code build.gradle} file, as described in | |
| <a href="#setup">Set Up Your Testing Environment</a>. | |
| </li> | |
| <li>At the beginning of your unit test class definition, add the | |
| {@code @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. | |
| </li> | |
| <li>To create a mock object for an Android dependency, add the {@code @Mock} annotation before | |
| the field declaration.</li> | |
| <li>To stub the behavior of the dependency, you can specify a condition and return | |
| value when the condition is met by using the {@code when()} and {@code thenReturn()} methods. | |
| </li> | |
| </ol> | |
| <p> | |
| The following example shows how you might create a unit test that uses a mock | |
| {@link android.content.Context} object. | |
| </p> | |
| <pre> | |
| 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)); | |
| } | |
| } | |
| </pre> | |
| <p> | |
| To learn more about using the Mockito framework, see the | |
| <a href="http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html" | |
| class="external-link">Mockito API reference</a> and the | |
| {@code SharedPreferencesHelperTest} class in the | |
| <a href="https://github.com/googlesamples/android-testing/tree/master/unit/BasicSample" | |
| class="external-link">sample code</a>. | |
| </p> | |
| <p>If the exceptions thrown by Android APIs in the | |
| <code>android.jar</code> are problematic for your tests, you can change the behavior so that methods | |
| instead return either null or zero by adding the following configuration in your project's | |
| top-level <code>build.gradle</code> file:</p> | |
| <pre> | |
| android { | |
| ... | |
| testOptions { | |
| unitTests.returnDefaultValues = true | |
| } | |
| } | |
| </pre> | |
| <p class="caution"><strong>Caution:</strong> | |
| Setting the <code>returnDefaultValues</code> property to <code>true</code> | |
| should be done with care. The null/zero return values can introduce | |
| regressions in your tests, which are hard to debug and might allow failing tests | |
| to pass. Only use it as a last resort.</p> | |
| <h2 id="run">Run Local Unit Tests</h2> | |
| <p>To run your local unit tests, follow these steps:</p> | |
| <ol> | |
| <li>Be sure your project is synchronized with Gradle by clicking | |
| <b>Sync Project</b> <img src="/images/tools/sync-project.png" alt="" | |
| class="inline-icon"> in the toolbar.</li> | |
| <li>Run your test in one of the following ways: | |
| <ul> | |
| <li>To run a single test, open the <b>Project</b> window, and then | |
| right-click a test and click <strong>Run</strong> <img src= | |
| "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.</li> | |
| <li>To test all methods in a class, right-click a class or method in the | |
| test file and click <b>Run</b> <img src= | |
| "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">. | |
| <li>To run all tests in a directory, right-click on the | |
| directory and select <strong>Run tests</strong> <img src= | |
| "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">. | |
| </li> | |
| </ul> | |
| </li> | |
| </ol> | |
| <p> | |
| The Android Plugin for Gradle compiles the local unit test code located in | |
| the default directory ({@code src/test/java/}), builds a test app, and | |
| executes it locally using the default test runner class. Android Studio then | |
| displays the results in the <b>Run</b> window. | |
| </p> |