Тестирование пользовательского интерфейса Android с имитацией зависимостей

У меня есть активность, в которой я предоставляю кнопку. Нажатие на кнопку вызывает метод в классе поставщика данных, и на основе возвращаемого значения метода я вношу изменения в пользовательский интерфейс. Теперь я хочу написать инструментальный тест, в котором я выполняю click() на кнопке, но избегаю фактического вызова метода в классе поставщика данных. Вместо этого я хочу вернуть желаемое значение из метода, а затем проверить, был ли соответствующим образом изменен пользовательский интерфейс.

Моя активность

@Override
    public void onCreate(final Bundle savedInstanceState) {
        mActionButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(final View v) {
                boolean result = dataProvider.getResult();
                if (result) {
                   mSuccessTextView.setVisibility(View.VISIBLE);
                }
            }
        });
    }

Здесь при нажатии кнопки выполняется вызов DataProvider#getResult, и результат этого метода сохраняется в result. Если результат true, TextView mSuccessTextView, ранее GONE, теперь создается VISIBLE.
Проблема здесь в том, что DataProvider#getResult имеет дело с множеством внешних компонентов, которые делают тестирование невозможным. Итак, что я хочу сделать, так это использовать фиктивный экземпляр DataProvider, чтобы я мог заставить getResult вернуть желаемое значение, а затем проверить видимость mSuccessTextView. Это то, что я пробовал:

MyActivityTest.java

@RunWith(AndroidJUnit4.class)
public class MyActivityTest {

    private DataProvider mDataProvider;

    @Rule
    public IntentsTestRule<MyActivity> mIntentRule =
            new IntentsTestRule<>(MyClientActivity.class);

    @Before
    public void setUp() {
        mDataProvider = mock(DataProvider.class);
    }

    @Test
    public void testResultSuccess() {
        boolean result = true;
        when(mDataProvider.getResult()).thenReturn(result);
        onView(withId(R.id.action_button)).perform(click());
        onView(withId(R.id.success_text_view)).check((ViewAssertion) isDisplayed());
    }
}

Выполнение вышеуказанного приводит к следующей ошибке:

org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: class com.domain.myapp.DataProvider.

Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.

Underlying exception : java.lang.UnsupportedOperationException: Cannot define class using reflection
.
.
.
Caused by: java.lang.UnsupportedOperationException: Cannot define class using reflection
.
.
.
Caused by: java.lang.IllegalStateException: This JVM's version string does not seem to be valid: 0
.
.
.
0
0
106
1

Ответы 1

Даже если бы вы могли издеваться над DataProvider, это не помогло бы вам, потому что вы не внедряете его экземпляр в MyClientActivity во время теста. Причины невозможности издеваться над DataProvider неизвестны, пожалуйста, предоставьте класс.

Почему нельзя издеваться DataProvider ? Говоря независимо от содержимого класса, я могу издеваться над ним во время модульного тестирования, поскольку это общедоступный и не окончательный класс. Почему я не могу издеваться над ним во время инструментального тестирования?

iammrmehul 02.04.2019 15:49

Другие вопросы по теме