Skip to content

Unit Testing

Daniel Molinero edited this page Sep 1, 2018 · 7 revisions

2 Steps initialization

Whenever you are testing using mocks, there are 2 steps:

  1. Creating the mocks.
  2. Setting/Injecting the mocks in the class under test.

For the first one, you can use any of the already available solutions: Mockito, EasyMock, etc. Toothpick takes care of the second one without changing your production code.

Creating the mocks

Creating the mocks is pretty simple, for instance with Mockito we only need to add a JUnit rule and annotate some fields where the mocks will be created:

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

@Mock myDependency1 myDependency1;
@Mock myDependency2 myDependency2;

The rule will create the mocks before any of your tests (@Test) or non-static set up methods (@Before) are called. Now we need to inject this dependencies inside the class under test!

Injecting the mocks

For injecting the mocks, Toothpick defines another rule:

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
@Rule public ToothPickRule toothPickRule = new ToothPickRule(this, "Test Scope"); // 1

@Mock myDependency1 myDependency1;
@Mock myDependency2 myDependency2;

@Inject MyClassUnderTest myClass; // 2

@Before
public void setUp() throws Exception {
    toothPickRule.inject(this); // 3
}

The rule works in the following way:

  1. Initializing rule with 2 parameters:
    • Object containing the mocks (defined with @Mock).
    • Name of the scope that will be used to inject the mocks inside the class under test.
  2. Defining the class under test and annotating it with @Inject.
  3. Injecting the class under test with scope defined on the first step.

This approach works for field, method and construction injection.

Javax annotations and dex issues

Javax annotations have a runtime retention, this means that when creating the APK, all classes where these annotations are present will go to the first dex. This could overload the first dex by exceeding the number of methods references in it. This is an unlikely issue and we only know of one application with this problem. Nevertheless, to solve this issue, TP comes with one extra artifact where the retention for some of the javax annotation is changed.

To use it, simply define the dependency on your build.gradle and make sure that the default javax annotation are not included.

build.gradle
------------

implementation 'com.github.stephanenicolas.toothpick:toothpick-javax-annotations:1.1.3'

Why is it inside the Unit Testing section? Cause in order for the ToothpickRule to work, you need to get rid of toothpick-javax-annotations in your tests:

build.gradle
------------

configurations {
  // Make sure unit tests use only the real javax.inject annotations
  testImplementation.exclude module: 'toothpick-javax-annotations'
}