Instrumentation Testing with Dagger and Espresso

dagger_espressoOver the Christmas holidays Google has integrated the Espresso testing framework into its android built tools and bumped the version to 2.0. Old espresso maven repos went dead because of that which forced us to temporally move to Jake Wharton’s repo until we got the time to move. I was the fortunate one who had to make the switch. This post describes the pitfalls of the upgrade.

Pure espresso upgrade is described here:

https://code.google.com/p/android-test-kit/wiki/EspressoSetupInstructions

And we found a great article:

http://engineering.circle.com/instrumentation-testing-with-dagger-mockito-and-espresso/

which describes how to use the new Espresso 2.0 along with the new Dagger dependency injection framework. Really nice stuff and it is worth reading and seeing the code samples on github. It inspired me to try out the new Dagger 2.0 (http://google.github.io/dagger/) along with Espresso.

I encountered following pitfalls when modifying our app:

StackOverflowException during compilation

Check that your Module graph does not have a circular dependency among your providers. IE provider A requires B, but B requires provider A. Dagger does not seem to detect that and falls with Stack overflow.

NullPointerException during compilation

Apparently Dagger Modules can not be subclassed. I wanted to mock only some of providers of our quite large module so I wanted to create a simple module hierarchy and override only provider methods that I really want to mock. Check that your module does not inherit from other module.

No provider can throw exception during initialization

Well this is a no brainer, but if you are converting an existing project chances are that some of your constructors are throwing checked exceptions :). Had to refactor that.

java.lang.NoClassDefFoundError: com/app/data/DebugDataModule$$ProvideFactory

Solved by changing dependency definition of espresso:
androidTestCompile ('com.android.support.test.espresso:espresso-core:2.0') {
    exclude group: 'javax.inject'
}

Injecting content providers

The example project I mentioned above does not work well for content providers as for whatever reasons ContentProvider onCreate may be called before Application’s onCreate which leads to NPE when we try to use uninitialized Application static instance. Solved that by moving the injection to first content provider usage. If injected classes are null then obtain the Graph and inject them, otherwise let it go.