Модульное тестирование на Android Studio: ошибка "не издевательство"

Я новичок в Android Studio. Я использую Android Studio 1.2 Preview 2, gradle 2.2.1 и gradle plugin 1.1.0.

Я не могу обойти эту ошибку при попытке выполнить мои модульные тесты:

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

Это мой тестовый класс:

public class AppPreferencesTest extends InstrumentationTestCase {

AppPreferences preferences;

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

...

В моем файле build.gradle:

testCompile 'junit:junit:4.12'

Я попытался добавить это

testOptions { 
    unitTests.returnDefaultValues = true
}

потому что это было упомянуто в шагах, которые я выполнил в http://tools.android.com/tech-docs/unit-testing-support но это не исправляет.

Я также попытался создать MockContext:

preferences = new AppPreferences(new MockContext());

но конструктор AppPreferences, чем дает ошибку

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

...

RuntimeException: Method getDefaultSharedPreferences in android.preference.PreferenceManager not mocked.

Ответ 1

Я не мог получить тесты Instrumentation для работы, используя Android Studio, я думаю, они все еще завершают реализацию. И так как для эмуляции требуется запустить, есть более быстрые опции: регулярные модульные тесты.

Благодаря советам Джареда я переключился на Robolectric, который прост в использовании на Android Studio.

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

и

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());
    }

    ...

Информация здесь кажется правильной в это время: http://nenick-android.blogspot.nl/2015/02/android-studio-110-beta-4-and.html Но, вероятно, в ближайшем будущем, скорее всего, будет еще хуже, поскольку вся информация, которую я нашел на эту тему, с помощью Google уже устарела.

Ответ 2

Я вижу, что вы обновили свой вопрос.

Пожалуйста, взгляните на источник этого SharedPreferencesMockContext.java: https://github.com/applicake/Beandroid/blob/master/Beanstalk%20Android%20ClientTest/src/com/applicake/beanstalkclient/test/SharedPreferencesMockContext.java.

Вот тест: https://github.com/applicake/Beandroid/blob/master/Beanstalk%20Android%20ClientTest/src/com/applicake/beanstalkclient/test/NotificationsTests.java

Вот фрагмент показывает, как они создали свой макет:

  @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();
  }

Я столкнулся с этой ошибкой прошлой ночью. Попробуйте использовать "MockContext".

public class AppPreferencesTest extends InstrumentationTestCase {

AppPreferences preferences;
Context context;

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

Смотрите другие примеры здесь: fooobar.com/info/150696/...