11

I'm creating a test with Mockito. In the test, I'm creating an object of type ContentValues. When I run this test, I'm getting error:

java.lang.RuntimeException: Method put in android.content.ContentValues not mocked.

Here is the minimal code:

import android.content.ContentValues;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
    @Test
    public void test1() {
        ContentValues cv = new ContentValues();
        cv.put("key", "value");
    }
}

What to do to avoid this error?

1 Answers1

23

You are using a library designed for mocking, that lacks implementions. Because your test actually calls the method on the object, without using a mocking library to give it behavior, it's giving you that message.

As on the Android Unit Testing Support page:

"Method ... not mocked."

The android.jar file that is used to run unit tests does not contain any actual code - that is provided by the Android system image on real devices. Instead, all methods throw exceptions (by default). This is to make sure your unit tests only test your code and do not depend on any particular behaviour of the Android platform (that you have not explicitly mocked e.g. using Mockito). If that proves problematic, you can add the snippet below to your build.gradle to change this behavior:

android {
  // ...
  testOptions { 
    unitTests.returnDefaultValues = true
  }
}

To work around it, use a mocking framework like Mockito instead of calling real methods like put, or switch to Robolectric to use Java equivalents of classes otherwise implemented only in native code.

Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • I get an error: **java.lang.NoClassDefFoundError: android/os/Handler** – IgorGanapolsky Jan 30 '18 at 17:29
  • I am not a big fan of this behavior. For instance, I have on some classes code that takes out extras of intents and put those values into other intents, based on the extras of the original intent. It's still my code that transfers and filters and splits that data. I can not unit test this unless I mock every single combination of any data that causes different splits... Would be MUCH easier to test if the intent just... well... behaves like an Intent. This causes THOUSANDS of mocking lines just to build all combinations which could've been done with ZERO lines. No need to mock passive objects. – Grisgram Dec 14 '18 at 07:35
  • @Grisgram In that case [Robolectric](http://robolectric.org) might be up your alley; it simulates most of Android with JVM-friendly implementations. You can also run good old [instrumentation tests](https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests) to run against real APIs on a simulated device, but for something like Intent packing frankly I'd just favor Robolectric. – Jeff Bowman Dec 14 '18 at 15:57
  • 1
    `returnDefaultValues` changed to `isReturnDefaultValues` – Nelson Almendra Oct 24 '21 at 22:35