Home | History | Annotate | Download | only in unit-testing
      1 page.title=Building Local Unit Tests
      2 page.tags=testing,androidjunitrunner,junit,unit test,mock
      3 trainingnavtop=true
      4 
      5 @jd:body
      6 
      7 <!-- This is the training bar -->
      8 <div id="tb-wrapper">
      9 <div id="tb">
     10 
     11   <h2>This lesson teaches you to</h2>
     12 
     13   <ol>
     14     <li><a href="#setup">Set Up Your Testing Environment</a></li>
     15     <li><a href="#build">Create a Local Unit Test Class</a>
     16       <ol>
     17         <li><a href="#mocking-dependencies">Mock Android dependencies</a></li>
     18       </ol>
     19     </li>
     20     <li><a href="#run">Run Local Unit Tests</a></li>
     21   </ol>
     22 
     23   <h2>Try it out</h2>
     24 
     25   <ul>
     26     <li>
     27 <a href="https://github.com/googlesamples/android-testing/tree/master/unit/BasicSample"
     28 class="external-link">Local Unit Tests Code Samples</a></li>
     29     <li><a href="https://codelabs.developers.google.com/codelabs/android-testing/index.html?index=..%2F..%2Findex#0"
     30 class="external-link">Android Testing Codelab</a></li>
     31   </ul>
     32 </div>
     33 </div>
     34 
     35 <p>If your unit test has no dependencies or only has simple dependencies on Android, you should run
     36 your test on a local development machine. This testing approach is efficient because it helps
     37 you avoid the overhead of loading the target app and unit test code onto a physical device or
     38 emulator every time your test is run. Consequently, the execution time for running your unit
     39 test is greatly reduced. With this approach, you normally use a mocking framework, like
     40 <a href="https://github.com/mockito/mockito" class="external-link">Mockito</a>, to fulfill any
     41 dependency relationships.</p>
     42 
     43 <h2 id="setup">Set Up Your Testing Environment</h2>
     44 
     45 <p>In your Android Studio project, you must store the source files for local
     46 unit tests at <code><var>module-name</var>/src/test/java/</code>. This directory
     47 already exists when you create a new project.</p>
     48 
     49 <p>You also need to configure the testing dependencies for your project to use
     50 the standard APIs provided by the JUnit 4 framework. If your test needs to
     51 interact with Android dependencies, include the <a href=
     52 "https://github.com/mockito/mockito" class="external-link">Mockito</a> library
     53 to simplify your local unit tests. To learn more about using mock objects in
     54 your local unit tests, see <a href=
     55 "{@docRoot}training/testing/unit-testing/local-unit-tests.html#mocking-dependencies">
     56 Mocking Android dependencies</a>.</p>
     57 
     58 <p>In your app's top-level {@code build.gradle} file, you need to specify these
     59 libraries as dependencies:</p>
     60 
     61 <pre>
     62 dependencies {
     63     // Required -- JUnit 4 framework
     64     testCompile 'junit:junit:4.12'
     65     // Optional -- Mockito framework
     66     testCompile 'org.mockito:mockito-core:1.10.19'
     67 }
     68 </pre>
     69 
     70 
     71 <h2 id="build">Create a Local Unit Test Class</h2>
     72 
     73 <p>Your local unit test class should be written as a JUnit 4 test class.
     74 <a href="http://junit.org/" class="external-link">JUnit</a> is the most popular
     75 and widely-used unit testing framework for Java. The latest version of this framework, JUnit 4,
     76 allows you to write tests in a cleaner and more flexible way than its predecessor versions. Unlike
     77 the previous approach to Android unit testing based on JUnit 3, with JUnit 4, you do not need to
     78 extend the {@code junit.framework.TestCase} class. You also do not need to prefix your test method
     79 name with the {@code test} keyword, or use any classes in the {@code junit.framework} or
     80 {@code junit.extensions} package.</p>
     81 
     82 <p>To create a basic JUnit 4 test class, create a Java class that contains one or more test methods.
     83 A test method begins with the {@code &#64;Test} annotation and contains the code to exercise
     84 and verify a single functionality in the component that you want to test.</p>
     85 
     86 <p>The following example shows how you might implement a local unit test class. The test method
     87 {@code emailValidator_CorrectEmailSimple_ReturnsTrue} verifies that the {@code isValidEmail()}
     88 method in the app under test returns the correct result.</p>
     89 
     90 <pre>
     91 import org.junit.Test;
     92 import java.util.regex.Pattern;
     93 import static org.junit.Assert.assertFalse;
     94 import static org.junit.Assert.assertTrue;
     95 
     96 public class EmailValidatorTest {
     97 
     98     &#64;Test
     99     public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
    100         assertThat(EmailValidator.isValidEmail("name&#64;email.com"), is(true));
    101     }
    102     ...
    103 }
    104 </pre>
    105 
    106 <p>To test that components in your app return the expected results, use the
    107 <a href="http://junit.org/javadoc/latest/org/junit/Assert.html" class="external-link">
    108 junit.Assert</a> methods to perform validation checks (or <em>assertions</em>) to compare the state
    109 of the component under test against some expected value. To make tests more readable, you
    110 can use <a href="https://github.com/hamcrest" class="external-link">
    111 Hamcrest matchers</a> (such as the {@code is()} and {@code equalTo()} methods) to match the
    112 returned result against the expected result.</p>
    113 
    114 <h3 id="mocking-dependencies">Mock Android dependencies</h3>
    115 <p>
    116 By default, the <a href="{@docRoot}tools/building/plugin-for-gradle.html">
    117 Android Plug-in for Gradle</a> executes your local unit tests against a modified
    118 version of the {@code android.jar} library, which does not contain any actual code. Instead, method
    119 calls to Android classes from your unit test throw an exception.
    120 </p>
    121 <p>
    122 You can use a mocking framework to stub out external dependencies in your code, to easily test that
    123 your component interacts with a dependency in an expected way. By substituting Android dependencies
    124 with mock objects, you can isolate your unit test from the rest of the Android system while
    125 verifying that the correct methods in those dependencies are called. The
    126 <a href="https://github.com/mockito/mockito" class="external-link">Mockito</a> mocking framework
    127 for Java (version 1.9.5 and higher) offers compatibility with Android unit testing.
    128 With Mockito, you can configure mock objects to return some specific value when invoked.</p>
    129 
    130 <p>To add a mock object to your local unit test using this framework, follow this programming model:
    131 </p>
    132 
    133 <ol>
    134 <li>
    135 Include the Mockito library dependency in your {@code build.gradle} file, as described in
    136 <a href="#setup">Set Up Your Testing Environment</a>.
    137 </li>
    138 <li>At the beginning of your unit test class definition, add the
    139 {@code &#64;RunWith(MockitoJUnitRunner.class)} annotation. This annotation tells the Mockito test
    140 runner to validate that your usage of the framework is correct and simplifies the initialization of
    141 your mock objects.
    142 </li>
    143 <li>To create a mock object for an Android dependency, add the {@code &#64;Mock} annotation before
    144 the field declaration.</li>
    145 <li>To stub the behavior of the dependency, you can specify a condition and return
    146 value when the condition is met by using the {@code when()} and {@code thenReturn()} methods.
    147 </li>
    148 </ol>
    149 
    150 <p>
    151 The following example shows how you might create a unit test that uses a mock
    152 {@link android.content.Context} object.
    153 </p>
    154 
    155 <pre>
    156 import static org.hamcrest.MatcherAssert.assertThat;
    157 import static org.hamcrest.CoreMatchers.*;
    158 import static org.mockito.Mockito.*;
    159 import org.junit.Test;
    160 import org.junit.runner.RunWith;
    161 import org.mockito.Mock;
    162 import org.mockito.runners.MockitoJUnitRunner;
    163 import android.content.SharedPreferences;
    164 
    165 &#64;RunWith(MockitoJUnitRunner.class)
    166 public class UnitTestSample {
    167 
    168     private static final String FAKE_STRING = "HELLO WORLD";
    169 
    170     &#64;Mock
    171     Context mMockContext;
    172 
    173     &#64;Test
    174     public void readStringFromContext_LocalizedString() {
    175         // Given a mocked Context injected into the object under test...
    176         when(mMockContext.getString(R.string.hello_word))
    177                 .thenReturn(FAKE_STRING);
    178         ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
    179 
    180         // ...when the string is returned from the object under test...
    181         String result = myObjectUnderTest.getHelloWorldString();
    182 
    183         // ...then the result should be the expected one.
    184         assertThat(result, is(FAKE_STRING));
    185     }
    186 }
    187 </pre>
    188 
    189 <p>
    190 To learn more about using the Mockito framework, see the
    191 <a href="http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html"
    192 class="external-link">Mockito API reference</a> and the
    193 {@code SharedPreferencesHelperTest} class in the
    194 <a href="https://github.com/googlesamples/android-testing/tree/master/unit/BasicSample"
    195 class="external-link">sample code</a>.
    196 </p>
    197 
    198 
    199 <h2 id="run">Run Local Unit Tests</h2>
    200 
    201 <p>To run your local unit tests, follow these steps:</p>
    202 
    203 <ol>
    204 
    205   <li>Be sure your project is synchronized with Gradle by clicking
    206   <b>Sync Project</b> <img src="/images/tools/sync-project.png" alt=""
    207   class="inline-icon"> in the toolbar.</li>
    208 
    209   <li>Run your test in one of the following ways:
    210     <ul>
    211       <li>To run a single test, open the <b>Project</b> window, and then
    212   right-click a test and click <strong>Run</strong> <img src=
    213   "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.</li>
    214       <li>To test all methods in a class, right-click a class or method in the
    215 test file and click <b>Run</b> <img src=
    216   "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.
    217       <li>To run all tests in a directory, right-click on the
    218       directory and select <strong>Run tests</strong> <img src=
    219       "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.
    220       </li>
    221     </ul>
    222   </li>
    223 
    224 </ol>
    225 
    226 <p>
    227   The Android Plugin for Gradle compiles the local unit test code located in
    228   the default directory ({@code src/test/java/}), builds a test app, and
    229   executes it locally using the default test runner class. Android Studio then
    230   displays the results in the <b>Run</b> window.
    231 </p>
    232