blob: 893d957fcc41ca7da09e885730527f027860d1f8 [file] [log] [blame]
Quddus Chong4bc762a2015-04-07 16:42:24 -07001page.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 <h2>Dependencies and Prerequisites</h2>
11
12 <ul>
Trevor Johns682c24e2016-04-12 10:13:47 -070013 <li><a href="{@docRoot}tools/studio/index.html">Android Studio (latest version)</a>.</li>
Quddus Chong4bc762a2015-04-07 16:42:24 -070014 </ul>
15
16 <h2>This lesson teaches you to</h2>
17
18 <ol>
19 <li><a href="#setup">Set Up Your Testing Environment</a></li>
20 <li><a href="#build">Create a Local Unit Test Class</a></li>
21 <li><a href="#run">Run Local Unit Tests</a></li>
22 </ol>
23
24 <h2>Try it out</h2>
25
26 <ul>
27 <li>
Trevor Johns682c24e2016-04-12 10:13:47 -070028<a href="https://github.com/googlesamples/android-testing/tree/master/unit/BasicSample"
Quddus Chong4bc762a2015-04-07 16:42:24 -070029class="external-link">Local Unit Tests Code Samples</a></li>
Trevor Johns682c24e2016-04-12 10:13:47 -070030 <li><a href="https://codelabs.developers.google.com/codelabs/android-testing/index.html?index=..%2F..%2Findex#0"
31class="external-link">Android Testing Codelab</a></li>
Quddus Chong4bc762a2015-04-07 16:42:24 -070032 </ul>
33</div>
34</div>
35
36<p>If your unit test has no dependencies or only has simple dependencies on Android, you should run
37your test on a local development machine. This testing approach is efficient because it helps
38you avoid the overhead of loading the target app and unit test code onto a physical device or
39emulator every time your test is run. Consequently, the execution time for running your unit
40test is greatly reduced. With this approach, you normally use a mocking framework, like
Trevor Johns682c24e2016-04-12 10:13:47 -070041<a href="https://github.com/mockito/mockito" class="external-link">Mockito</a>, to fulfill any
Quddus Chong4bc762a2015-04-07 16:42:24 -070042dependency relationships.</p>
43
Quddus Chong4bc762a2015-04-07 16:42:24 -070044<h2 id="setup">Set Up Your Testing Environment</h2>
Trevor Johns682c24e2016-04-12 10:13:47 -070045<p>Before building your local unit test, make sure to configure your test source code location and
46project dependencies, as described in
47<a href="{@docRoot}training/testing/start/index.html#config-local-tests">
48Getting Started with Testing</a>.</p>
Quddus Chong4bc762a2015-04-07 16:42:24 -070049
Quddus Chong4bc762a2015-04-07 16:42:24 -070050
51<h2 id="build">Create a Local Unit Test Class</h2>
52<p>Your local unit test class should be written as a JUnit 4 test class.
53<a href="http://junit.org/" class="external-link">JUnit</a> is the most popular
54and widely-used unit testing framework for Java. The latest version of this framework, JUnit 4,
55allows you to write tests in a cleaner and more flexible way than its predecessor versions. Unlike
56the previous approach to Android unit testing based on JUnit 3, with JUnit 4, you do not need to
57extend the {@code junit.framework.TestCase} class. You also do not need to prefix your test method
58name with the {@code test’} keyword, or use any classes in the {@code junit.framework} or
59{@code junit.extensions} package.</p>
60
61<p>To create a basic JUnit 4 test class, create a Java class that contains one or more test methods.
Trevor Johns682c24e2016-04-12 10:13:47 -070062A test method begins with the {@code &#64;Test} annotation and contains the code to exercise
Quddus Chong4bc762a2015-04-07 16:42:24 -070063and verify a single functionality in the component that you want to test.</p>
64
65<p>The following example shows how you might implement a local unit test class. The test method
66{@code emailValidator_CorrectEmailSimple_ReturnsTrue} verifies that the {@code isValidEmail()}
67method in the app under test returns the correct result.</p>
68
69<pre>
70import org.junit.Test;
71import java.util.regex.Pattern;
72import static org.junit.Assert.assertFalse;
73import static org.junit.Assert.assertTrue;
74
75public class EmailValidatorTest {
76
77 &#64;Test
78 public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
79 assertThat(EmailValidator.isValidEmail("name&#64;email.com"), is(true));
80 }
81 ...
82}
83</pre>
84
85<p>To test that components in your app return the expected results, use the
86<a href="http://junit.org/javadoc/latest/org/junit/Assert.html" class="external-link">
87junit.Assert</a> methods to perform validation checks (or <em>assertions</em>) to compare the state
88of the component under test against some expected value. To make tests more readable, you
Trevor Johns682c24e2016-04-12 10:13:47 -070089can use <a href="https://github.com/hamcrest" class="external-link">
Quddus Chong4bc762a2015-04-07 16:42:24 -070090Hamcrest matchers</a> (such as the {@code is()} and {@code equalTo()} methods) to match the
91returned result against the expected result.</p>
92
Quddus Chong4bc762a2015-04-07 16:42:24 -070093<h3 id="mocking-dependencies">Mocking Android dependencies</h3>
94<p>
95By default, the <a href="{@docRoot}tools/building/plugin-for-gradle.html">
96Android Plug-in for Gradle</a> executes your local unit tests against a modified
97version of the {@code android.jar} library, which does not contain any actual code. Instead, method
98calls to Android classes from your unit test throw an exception.
99</p>
100<p>
101You can use a mocking framework to stub out external dependencies in your code, to easily test that
102your component interacts with a dependency in an expected way. By substituting Android dependencies
103with mock objects, you can isolate your unit test from the rest of the Android system while
104verifying that the correct methods in those dependencies are called. The
Trevor Johns682c24e2016-04-12 10:13:47 -0700105<a href="https://github.com/mockito/mockito" class="external-link">Mockito</a> mocking framework
Quddus Chong4bc762a2015-04-07 16:42:24 -0700106for Java (version 1.9.5 and higher) offers compatibility with Android unit testing.
107With Mockito, you can configure mock objects to return some specific value when invoked.</p>
108
109<p>To add a mock object to your local unit test using this framework, follow this programming model:
110</p>
111
112<ol>
113<li>
114Include the Mockito library dependency in your {@code build.gradle} file, as described in
115<a href="#setup">Set Up Your Testing Environment</a>.
116</li>
117<li>At the beginning of your unit test class definition, add the
Trevor Johns682c24e2016-04-12 10:13:47 -0700118{@code &#64;RunWith(MockitoJUnitRunner.class)} annotation. This annotation tells the Mockito test
Quddus Chong4bc762a2015-04-07 16:42:24 -0700119runner to validate that your usage of the framework is correct and simplifies the initialization of
120your mock objects.
121</li>
Trevor Johns682c24e2016-04-12 10:13:47 -0700122<li>To create a mock object for an Android dependency, add the {@code &#64;Mock} annotation before
Quddus Chong4bc762a2015-04-07 16:42:24 -0700123the field declaration.</li>
124<li>To stub the behavior of the dependency, you can specify a condition and return
125value when the condition is met by using the {@code when()} and {@code thenReturn()} methods.
126</li>
127</ol>
128
129<p>
130The following example shows how you might create a unit test that uses a mock
131{@link android.content.Context} object.
132</p>
133
134<pre>
135import static org.hamcrest.MatcherAssert.assertThat;
136import static org.hamcrest.CoreMatchers.*;
137import static org.mockito.Mockito.*;
138import org.junit.Test;
139import org.junit.runner.RunWith;
140import org.mockito.Mock;
141import org.mockito.runners.MockitoJUnitRunner;
142import android.content.SharedPreferences;
143
144&#64;RunWith(MockitoJUnitRunner.class)
145public class UnitTestSample {
146
147 private static final String FAKE_STRING = "HELLO WORLD";
148
149 &#64;Mock
150 Context mMockContext;
151
152 &#64;Test
153 public void readStringFromContext_LocalizedString() {
154 // Given a mocked Context injected into the object under test...
155 when(mMockContext.getString(R.string.hello_word))
156 .thenReturn(FAKE_STRING);
157 ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
158
159 // ...when the string is returned from the object under test...
160 String result = myObjectUnderTest.getHelloWorldString();
161
162 // ...then the result should be the expected one.
163 assertThat(result, is(FAKE_STRING));
164 }
165}
166</pre>
167
168<p>
169To learn more about using the Mockito framework, see the
170<a href="http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html"
171class="external-link">Mockito API reference</a> and the
172{@code SharedPreferencesHelperTest} class in the
Trevor Johns682c24e2016-04-12 10:13:47 -0700173<a href="https://github.com/googlesamples/android-testing/tree/master/unit/BasicSample"
Quddus Chong4bc762a2015-04-07 16:42:24 -0700174class="external-link">sample code</a>.
175</p>
176
177<h2 id="run">Run Local Unit Tests</h2>
178<p>
Trevor Johns682c24e2016-04-12 10:13:47 -0700179To run your tests, follow the steps for running local unit tests
180described in <a href="{@docRoot}training/testing/start/index.html#run-local-tests">
181Getting Started with Testing</a>.
Quddus Chong4bc762a2015-04-07 16:42:24 -0700182</p>
Quddus Chong4bc762a2015-04-07 16:42:24 -0700183