5
votes

I added the following dependencies to my android project:

 // Unit testing dependencies
androidTestCompile 'junit:junit:4.12'
// Set this dependency if you want to use Mockito
androidTestCompile 'org.mockito:mockito-core:1.10.19'

And create a test using junit4 api (an example, Adder is a simple class that sums ints):

@RunWith(MockitoJUnitRunner.class) 
public class AdderTest {

    @Test
    public void testValidAdd() {
        Adder adder = new Adder();
        assertEquals(adder.add(1,1), 2);
    }
}

When I try to run the test, I get:

Running tests Test running started junit.framework.AssertionFailedError: No tests found in com.test.myapp.AdderTest at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176) at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701) Finish

I read here and here, but nothing helps.

Does anyone see what I'm doing wrong / have any input?

2
Unit tests belong in the test folder, so use testCompile. Also, you do not need the @RunWith(MockitoJUnitRunner.class). - Jared Burrows
This was just an example. I do need in my original project to use mocks. In addition, the code that I'm testing uses android.util.Patterns.EMAIL_ADDRESS, and it returns null when I run it as a unit test. If I run it as an Android instrumentation test, won't it return the actual matcher? - dors
Post your code for clarity. You should be using Robolectric for unit testing. It will instrument the classes you need so you do not need mocks for everything. - Jared Burrows
I do need to use Mockito to mock some responses of class dependencies. Using @RunWith(RobolectricTestRunner.class) in the test class + adding MockitoAnnotations.initMocks(this); to my setup() method does make my test work as a unit test (android.util.Patterns.EMAIL_ADDRESS does not return null). Is this the way to go though? It seems complex :/ - dors
It is not complex at all. Please see my Android Gradle Templaet here: github.com/jaredsburrows/AndroidGradleTemplate/blob/master/… - Jared Burrows

2 Answers

16
votes

These aren't unit tests, they are instrumentation test. I had the same problem and solved it by adding these lines to module's build.gradle:

android {
    ...
    sourceSets {
        ...
        defaultConfig {
            testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
        }
    }
}

You have to add the runner in dependencies, i suggest you espresso:

androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'

EDIT:

I have forgotten about the annotation. Just remove @RunWith and make a @Before method with line:

MockitoAnnotations.initMocks(this);

or:

System.setProperty("dexmaker.dexcache", InstrumentationRegistry.getTargetContext().getCacheDir().getPath());

I have to mention this way is not recommended. To use the second one, you have to add dependencies with dex-maker for mockito:

androidTestCompile ('com.google.dexmaker:dexmaker-mockito:1.2') {
        exclude module: 'mockito-core'
    }

Since you have added mockito, we have to exclude mockito core from the new dependency. It already contains the normal dex-maker module.

2
votes

You're using an Android Instrumentation test. By default, the Android test runner doesn't run on JUnit4, it runs on JUnit3 using subclasses of InstrumentationTestCase.

You'll need to revert to manual calls to MockitoAnnotations.initMocks(), with an optional tear-down call to Mockito.validateMockitoUsage(). Of course, calls directly to Mockito.mock (and such) will still work.

As an alternative, there is an official JUnit4 runner, which can be installed from the Android Support Test Library. By invoking this Instrumentation rather than the default test runner, you can run JUnit4 tests on your device, including using MockitoJUnitRunner or MockitoRule.