Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing on Android Studio: "not mocked" error

I am new to Android Studio. I am using Android Studio 1.2 preview 2, gradle 2.2.1 and gradle plugin 1.1.0.

I cannot get around this error, when trying to run my unit tests:

java.lang.RuntimeException: Method getInstrumentation in android.test.InstrumentationTestCase not mocked

This is my test class:

public class AppPreferencesTest extends InstrumentationTestCase {

AppPreferences preferences;

@Before
public void setUp() throws Exception {
    preferences = new AppPreferences(getInstrumentation().getTargetContext());
}

...

In my build.gradle:

testCompile 'junit:junit:4.12'

I tried adding this

testOptions { 
    unitTests.returnDefaultValues = true
}

because that was mentioned in the steps that I followed at http://tools.android.com/tech-docs/unit-testing-support but it does not fix it.

I also tried creating a MockContext:

preferences = new AppPreferences(new MockContext());

but the constructor of AppPreferences than gives an error

public AppPreferences(Context context) {
    preferences = PreferenceManager.getDefaultSharedPreferences(
            context);
}

...

RuntimeException: Method getDefaultSharedPreferences in android.preference.PreferenceManager not mocked.
like image 384
Frank Avatar asked Mar 17 '15 13:03

Frank


People also ask

What is mock function in unit testing?

What is mocking? Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to isolate and focus on the code being tested and not on the behavior or state of external dependencies.

How do I mock a method in Android?

To create a mock object for an Android dependency, add the @Mock annotation before the field declaration. To stub the behavior of the dependency, you can specify a condition and return value when the condition is met by using the when() and thenReturn() methods.

What is Mockito Android?

As a result, we simply mock the dependency class and test the Main Class. Mockito is a mocking framework with a delicious flavor. It has a clean and simple API that allows you to construct beautiful tests. The tests in Mockito are very readable and provide clear verification errors, so you won't get a hangover.


2 Answers

I see you have updated your question.

Please take a look at the source of this SharedPreferencesMockContext.java: https://github.com/applicake/Beandroid/blob/master/Beanstalk%20Android%20ClientTest/src/com/applicake/beanstalkclient/test/SharedPreferencesMockContext.java.

Here is the test: https://github.com/applicake/Beandroid/blob/master/Beanstalk%20Android%20ClientTest/src/com/applicake/beanstalkclient/test/NotificationsTests.java

Here is a snippet show how they created their Mock:

  @Override
  protected void setUp() throws Exception {

    final SharedPreferencesMockContext mockContext = new SharedPreferencesMockContext(getContext());
    MockApplication mockApplication = new MockApplication(){
      @Override
      public Context getApplicationContext() {
        Log.d("tests", "Im here");
        return mockContext;
      }
    };


    context = mockContext;
    setApplication(mockApplication);
    prefs = PreferenceManager.getDefaultSharedPreferences(context);
    prefs.edit().clear().commit();

    super.setUp();
  }

I ran into this error last night. Try using "MockContext".

public class AppPreferencesTest extends InstrumentationTestCase {

AppPreferences preferences;
Context context;

@Before
public void setUp() throws Exception {
    context = new MockContext();
    preferences = new AppPreferences(context);
}

Please see other examples here: https://stackoverflow.com/a/29063736/950427

like image 56
Jared Burrows Avatar answered Oct 23 '22 03:10

Jared Burrows


I couldn't get Instrumentation tests to work, using Android Studio, I guess they're still finalising the implementation. And since it needs to run on the emulator, there are faster options: regular unit tests.

Thanks to Jared's tips, I switched to Robolectric, which is easy to use on Android Studio.

androidTestCompile 'junit:junit:4.12'
androidTestCompile "org.robolectric:robolectric:3.0"

and

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.RobolectricTestRunner;
import static junit.framework.TestCase.assertEquals;

@RunWith(RobolectricTestRunner.class)
public class AppPreferencesTest {

    AppPreferences preferences;

    @Before
    public void setUp() throws Exception {
        preferences = new AppPreferences(RuntimeEnvironment.application.getApplicationContext());
    }

    @Test
    public void testIsNotificationsEnabled_Default() throws Exception {
        assertEquals(true, preferences.isNotificationsEnabled());
    }

    ...

The info here seems to be correct at this time: http://nenick-android.blogspot.nl/2015/02/android-studio-110-beta-4-and.html But will probably deprecate again in the near future, as all the info I found on this subject using google deprecated already.

like image 28
Frank Avatar answered Oct 23 '22 03:10

Frank