1## Testing
2
3### Do not rely on mocks
4
5All APIs created in Jetpack **must have a testing story**: how developers should
6write tests for their code that relies on a library, this story should not be
7"use Mockito to mock class `Foo`". Your goal as an API owner is to **create
8better alternatives** to mocking.
9
10#### Why can't I suggest mocks as testing strategy?
11
12Frequently, mocks don't follow guarantees outlined in the API they mock. That
13leads to:
14
15*   Significant difference in the behavior that diminishes test value.
16*   Brittle tests, that make hard to evolve both apps and libraries, because new
17    code may start to rely on the guarantees broken in a mock. Let's take a look
18    at a simplified example. So, let's say you mocked a bundle and getString in
19    it:
20
21    ```java
22    Bundle mock = mock(Bundle.class);
23    when(mock.getString("key")).thenReturn("result");
24    ```
25
26    But you don't mock it to simply call `getString()` in your test. A goal is
27    not to test a mock, the goal is always to test your app code, so your app
28    code always interacts with a mock in some way:
29
30    ```java
31    Bundle bundle = mock(Bundle.class);
32    when(mock.getString("key")).thenReturn("result");
33    mycomponent.consume(bundle)
34    ```
35
36    Originally the test worked fine, but over time `component.consume` is
37    evolving, and, for example, it may start to call `containsKey` on the given
38    bundle. But our test passes a mock that don't expect such call and, boom,
39    test is broken. However, component code is completely valid and has nothing
40    to do with the broken test. We observed a lot of issues like that during
41    updates of Android SDK and Jetpack libraries to newer versions internally at
42    google. Suggesting to mock our own components is shooting ourselves in the
43    foot, it will make adoption of newer version of libraries even slower.
44
45*   Messy tests. It always starts with simple mock with one method, but then
46    this mock grows with the project, and as a result test code has sub-optimal
47    half-baked class implementation of on top of the mock.
48
49#### But it's okay to mock interfaces, right?
50
51It depends. There are interfaces that don't imply any behavior guarantees and
52they are ok to be mocked. However, **not all** interfaces are like that: for
53example, `Map` is an interface but it has a lot of contracts required from
54correct implementation. Examples of interfaces that are ok to mock are callback
55interfaces in general, for example: `View.OnClickListener`, `Runnable`.
56
57#### What about spying?
58
59Spying on these classes is banned as well - Mockito spies permit stubbing of
60methods just like mocks do, and interaction verification is brittle and
61unnecessary for these classes. Rather than verifying an interaction with a
62class, developers should observe the result of an interaction - the effect of a
63task submitted to an `Executor`, or the presence of a fragment added to your
64layout. If an API in your library misses a way to have such checks, you should
65add methods to do that.
66
67#### Avoid Mockito in your own tests
68
69One of the things that would help you to identify if your library is testable
70without Mockito is not using Mockito yourself. Yes, historically we heavily
71relied on Mockito ourselves and old tests are not rewritten, but new tests
72shouldn't follow up that and should take as an example good citizens, for
73example, `-ktx` modules. These modules don't rely on Mockito and have concise
74expressive tests.
75
76One of the popular and legit patterns for Mockito usage were tests that verify
77that a simple callback-like interface receives correct parameters.
78
79```java
80class MyApi {
81   interface Callback {
82     void onFoo(Value value);
83  }
84  void foo() { … }
85  void registerFooCallback(Callback callback) {...}
86}
87```
88
89In API like the one above, in Java 7 tests for value received in `Callback`
90tended to become very wordy without Mockito. But now in your tests you can use
91Kotlin and test will be as short as with Mockito:
92
93```kotlin
94fun test() {
95    var receivedValue = null
96    myApi.registerCallback { value -> receivedValue = value }
97    myApi.foo()
98   // verify receivedValue
99}
100```
101
102#### Don't compromise in API to enable Mockito
103
104Mockito on Android
105[had an issue](https://github.com/Mockito/Mockito/issues/1173) with mocking
106final classes. Moreover, internally at Google this feature is disabled even for
107non-Android code. So you may hear complaints that some of your classes are not
108mockable, however **it is not a reason for open up a class for extension**. What
109you should instead is verify that is possible to write the same test without
110mocking, if not, again you should **provide better alternative in your API**.
111
112#### How do I approach testing story for my API?
113
114The best way is to step into developer's shoes and write a sample app that is a
115showcase for your API, then go to the next step - test that code also. If you
116are able to implement tests for your demo app, then users of your API will also
117be able to implement tests for functionalities where your API is also used.
118