Android Testing with JUnit & mockito

Tips, study notes, and mini-code samples

Ahmed Elshahawi
Sep 17, 2017 · 6 min read

If you are not writing tests, you are writing an instant legacy code

- Michael Feathers.

It is better to have a simple test that works, other than a complicated test that seems to work

- mockito documentation.

General Testing Tips

  • All tests must run really fast.
  • All tests must be small and focused, don’t do multiple assertions in one unit test.
  • All tests must reliable, not flaky.
  • Watch out when writing tests for edge cases.
  • Don’t include UI in tests, because it’s gonna be slow.
  • Replace WebService with dummy.
  • Mimic WebService behavior.
  • Use mocks & stubs.
  • It doesn’t matter what approach you take unless you are consistent about it.
  • Be pragmatic choose you and your team what you want to test, how you want to test it and be consistent about that.
  • Avoid singletons, so you won’t get any connections between tests.
  • Isolate non-testable code, make it a manageable risk.
  • Don’t use mockito spies, you will have side effects from one test to another.
  • Don’t nest mocks.
  • Avoid using dedicated methods, just for the sake of making things testable.
  • Don’t overuse power features.
  • Consider refactoring.
  • Prefer test on the Java JVM.

Behavioral Verification Verifies this method is called.

State-based Verification Verifies this method is called with those specific attributes.

  • A generated class that doesn’t do anything, used for behavior verification.
  • But it does do one thing actually, it has counters internally, that can detect which methods are called then used for behavior verification.
  • For void methods won’t return anything, for typed methods will return the default value.
  • A hand-written class that returns a pre-defined response given certain input, used for state verification.

JUnit

  • It uses annotations.
  • Each test is isolated.
  • Creates an instance of the class for every test case.
  • Instance variable doesn’t share state between 2 tests.
  • What happens in one test shouldn’t be affected by what happens in another.
  • You can share objects between those classes using static, but we are not supposed to be sharing things, and it’s not recommended behavior & not expected what is gonna happen from JUnit.
  • On the other hand, there are other testing libraries that share things between tests (TestNG).
  1. GIVEN
  • Initial conditions
  • Create instances

2. WHEN

  • Actually the actions we want to trigger
  • The thing we gonna be testing

3. THEN

  • Did it work, or it didn’t work

Rules are used to add additional functionality which applies to all tests within a test class but in a more generic way.

For instance, ExternalResource executes code before and after a test method, without having to use @Before and @After

Using an ExternalResource rather than @Before and @After gives opportunities for better code reuse; the same rule can be used from two different test classes.


Image for post
Image for post
http://site.mockito.org

Why mockito is easy-to-use

  • Very readable syntax
  • Has no learning curve
  • With annotations support
  • Mature with large community support and very popular among Android & Java developers

mockito has a limitation, you can’t mock static methods.

How to start

app/build.gradle

Initializing mockito

Verifying interactions

Examples of both Behavioral Verification & State-based verification:

Stubbing methods

mockito Stubbing methods (calling methods & return our preferred values):

  • Normal Syntax
  • Alternative Syntax
  • BDD Syntax

Capturing Arguments

Used to test Asynchronous logic:

Don’t overuse this: many of the use-cases that this can be used for can be solved by using Argument Matchers.

Native type of mockito, you just annotate a member with @captor, so this is a Response captor which can capture an argument passed to a method of type Response:


UI Testing

  • We don’t wanna test the UI, but how to make sure our app is properly tested without having to inflate the UI.
  • You dumpify the UI, make it just a pass-through layer
  • We do this using the MVP:
Image for post
Image for post

It works,

  • Because of dependency injection
  • It’s a clean architecture “inward pointing”, all of the dependencies point in one direction, the view implementation depends on the presenter, but the presenter doesn’t depend on the view implementation directly

Testing data

You just create your own mock implementation of the data class and override all of the methods in that class & have them return a value appropriate for your testing:

New Creation

Avoid creating objects internally in other objects because that makes things hard to test, use dependency injection instead:

If the user doesn’t need one internal object but multiple of them for method calls, In that case, we can inject a web-service factory of type “factory pattern”:

Dependency injection is a bit of loaded term in the Android community, It is not more than just injecting dependencies into constructor.


Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app