• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Building Local Unit Tests
2page.tags=testing,androidjunitrunner,junit,unit test,mock
3trainingnavtop=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"
28class="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"
30class="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
36your test on a local development machine. This testing approach is efficient because it helps
37you avoid the overhead of loading the target app and unit test code onto a physical device or
38emulator every time your test is run. Consequently, the execution time for running your unit
39test 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
41dependency 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
46unit tests at <code><var>module-name</var>/src/test/java/</code>. This directory
47already exists when you create a new project.</p>
48
49<p>You also need to configure the testing dependencies for your project to use
50the standard APIs provided by the JUnit 4 framework. If your test needs to
51interact with Android dependencies, include the <a href=
52"https://github.com/mockito/mockito" class="external-link">Mockito</a> library
53to simplify your local unit tests. To learn more about using mock objects in
54your local unit tests, see <a href=
55"{@docRoot}training/testing/unit-testing/local-unit-tests.html#mocking-dependencies">
56Mocking Android dependencies</a>.</p>
57
58<p>In your app's top-level {@code build.gradle} file, you need to specify these
59libraries as dependencies:</p>
60
61<pre>
62dependencies {
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
75and widely-used unit testing framework for Java. The latest version of this framework, JUnit 4,
76allows you to write tests in a cleaner and more flexible way than its predecessor versions. Unlike
77the previous approach to Android unit testing based on JUnit 3, with JUnit 4, you do not need to
78extend the {@code junit.framework.TestCase} class. You also do not need to prefix your test method
79name 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.
83A test method begins with the {@code @Test} annotation and contains the code to exercise
84and 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()}
88method in the app under test returns the correct result.</p>
89
90<pre>
91import org.junit.Test;
92import java.util.regex.Pattern;
93import static org.junit.Assert.assertFalse;
94import static org.junit.Assert.assertTrue;
95
96public 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">
108junit.Assert</a> methods to perform validation checks (or <em>assertions</em>) to compare the state
109of the component under test against some expected value. To make tests more readable, you
110can use <a href="https://github.com/hamcrest" class="external-link">
111Hamcrest matchers</a> (such as the {@code is()} and {@code equalTo()} methods) to match the
112returned result against the expected result.</p>
113
114<h3 id="mocking-dependencies">Mock Android dependencies</h3>
115
116<p>By default, the <a href=
117"{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for
118Gradle</a> executes your local unit tests against a modified version of the
119{@code android.jar} library, which does not contain any actual code. Instead,
120method calls to Android classes from your unit test throw an exception. This is
121to make sure you test only your code and do not depend on any
122particular behavior of the Android platform (that you have not explicitly
123mocked).</p>
124
125<p>
126You can use a mocking framework to stub out external dependencies in your code, to easily test that
127your component interacts with a dependency in an expected way. By substituting Android dependencies
128with mock objects, you can isolate your unit test from the rest of the Android system while
129verifying that the correct methods in those dependencies are called. The
130<a href="https://github.com/mockito/mockito" class="external-link">Mockito</a> mocking framework
131for Java (version 1.9.5 and higher) offers compatibility with Android unit testing.
132With Mockito, you can configure mock objects to return some specific value when invoked.</p>
133
134<p>To add a mock object to your local unit test using this framework, follow this programming model:
135</p>
136
137<ol>
138<li>
139Include the Mockito library dependency in your {@code build.gradle} file, as described in
140<a href="#setup">Set Up Your Testing Environment</a>.
141</li>
142<li>At the beginning of your unit test class definition, add the
143{@code @RunWith(MockitoJUnitRunner.class)} annotation. This annotation tells the Mockito test
144runner to validate that your usage of the framework is correct and simplifies the initialization of
145your mock objects.
146</li>
147<li>To create a mock object for an Android dependency, add the {@code @Mock} annotation before
148the field declaration.</li>
149<li>To stub the behavior of the dependency, you can specify a condition and return
150value when the condition is met by using the {@code when()} and {@code thenReturn()} methods.
151</li>
152</ol>
153
154<p>
155The following example shows how you might create a unit test that uses a mock
156{@link android.content.Context} object.
157</p>
158
159<pre>
160import static org.hamcrest.MatcherAssert.assertThat;
161import static org.hamcrest.CoreMatchers.*;
162import static org.mockito.Mockito.*;
163import org.junit.Test;
164import org.junit.runner.RunWith;
165import org.mockito.Mock;
166import org.mockito.runners.MockitoJUnitRunner;
167import android.content.SharedPreferences;
168
169&#64;RunWith(MockitoJUnitRunner.class)
170public class UnitTestSample {
171
172    private static final String FAKE_STRING = "HELLO WORLD";
173
174    &#64;Mock
175    Context mMockContext;
176
177    &#64;Test
178    public void readStringFromContext_LocalizedString() {
179        // Given a mocked Context injected into the object under test...
180        when(mMockContext.getString(R.string.hello_word))
181                .thenReturn(FAKE_STRING);
182        ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
183
184        // ...when the string is returned from the object under test...
185        String result = myObjectUnderTest.getHelloWorldString();
186
187        // ...then the result should be the expected one.
188        assertThat(result, is(FAKE_STRING));
189    }
190}
191</pre>
192
193<p>
194To learn more about using the Mockito framework, see the
195<a href="http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html"
196class="external-link">Mockito API reference</a> and the
197{@code SharedPreferencesHelperTest} class in the
198<a href="https://github.com/googlesamples/android-testing/tree/master/unit/BasicSample"
199class="external-link">sample code</a>.
200</p>
201
202<p>If the exceptions thrown by Android APIs in the
203<code>android.jar</code> are problematic for your tests, you can change the behavior so that methods
204instead return either null or zero by adding the following configuration in your project's
205top-level <code>build.gradle</code> file:</p>
206
207<pre>
208android {
209  ...
210  testOptions {
211    unitTests.returnDefaultValues = true
212  }
213}
214</pre>
215
216<p class="caution"><strong>Caution:</strong>
217Setting the <code>returnDefaultValues</code> property to <code>true</code>
218should be done with care. The null/zero return values can introduce
219regressions in your tests, which are hard to debug and might allow failing tests
220to pass. Only use it as a last resort.</p>
221
222
223<h2 id="run">Run Local Unit Tests</h2>
224
225<p>To run your local unit tests, follow these steps:</p>
226
227<ol>
228
229  <li>Be sure your project is synchronized with Gradle by clicking
230  <b>Sync Project</b> <img src="/images/tools/sync-project.png" alt=""
231  class="inline-icon"> in the toolbar.</li>
232
233  <li>Run your test in one of the following ways:
234    <ul>
235      <li>To run a single test, open the <b>Project</b> window, and then
236  right-click a test and click <strong>Run</strong> <img src=
237  "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.</li>
238      <li>To test all methods in a class, right-click a class or method in the
239test file and click <b>Run</b> <img src=
240  "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.
241      <li>To run all tests in a directory, right-click on the
242      directory and select <strong>Run tests</strong> <img src=
243      "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.
244      </li>
245    </ul>
246  </li>
247
248</ol>
249
250<p>
251  The Android Plugin for Gradle compiles the local unit test code located in
252  the default directory ({@code src/test/java/}), builds a test app, and
253  executes it locally using the default test runner class. Android Studio then
254  displays the results in the <b>Run</b> window.
255</p>
256