Робоэлектрик 3.8 с MVP и насмешкой setupActivity () - PullRequest
0 голосов
/ 07 мая 2018

Я использую архитектуру Android MVP и хочу проверить свой View. У меня есть следующий код в моем проекте:

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MainActivityTest {


    @Test
    public void testDisplay() throws Exception {
        MainActivity activity = Robolectric.setupActivity(MainActivity.class);

        final Menu menu = Shadows.shadowOf(activity).getOptionsMenu();

        assertEquals("Log", menu.findItem(R.id.menu_login).getTitle().toString());
    }

}

Тем не менее, я получаю ExceptionInIntializationError для какой-либо сторонней библиотеки, которая выбрасывает ее на шаге onResume () Activity, который вызывается Robolectric.

Кроме того, в onResume () Activity вызывается метод Presenter, который делает сетевой запрос .

Мои вопросы:

  1. Как смоделировать сторонний шаг инициализации? Я читал о Shadows , но я не знаю, как использовать их в этом конкретном сценарии. Я должен дразнить вещи во время setupActivity(...) звонка.
  2. Как смоделировать сетевой вызов? В моем коде MVP ведущий создается в методе onCreate (). Должен ли я перейти на шаблон внедрения прямой зависимости и перестроить архитектуру? Но этот подход будет конфликтовать с Robolectric.setupActivity(MainActivity.class);, так как мне понадобится какой-то хук для добавления содержимого в onCreate () или onResume () во время вызовов Robolectric.

1 Ответ

0 голосов
/ 07 мая 2018

Хорошо, я придумал следующее решение. Странно, что я никогда не видел подобных примеров на их странице или в статьях. Я использовал Mockito вместе с Robolectric .

Во-первых, я добавил метод setPresenter в Activity (представление MVP) для вставки пользовательского макета Presenter в представление

   @VisibleForTesting
    public void setPresenter(P presenter) {
        this.presenter = presenter;
    }

В моем коде Presenter создается во время метода onCreate (), поэтому я добавил null-check , чтобы добавить Presenter до onCreate () :

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (presenter == null)
        presenter = providePresenter(App.appComponentFrom(this));
    presenter.create();
}

В Robolectric Framework я нашел метод buildActivity(), который просто вызывает конструктор Activity (никаких методов жизненного цикла!).

Затем, после этого звонка, я сделал инъекцию своему ведущему.

Последний шаг - вызов activityController.setup().get(), как и тот же, что и setupActivity(), который вызывает методы жизненного цикла: create(), resume()

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MainActivityTest {

    @Mock
    CheckoutContract.Presenter presenter;

    private ShadowActivity mainActivity;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);

        ActivityController<MainActivity> activityController = Robolectric.buildActivity(MainActivity.class);
        activityController.get().setPresenter(presenter);
        mainActivity = Shadows.shadowOf(activityController.setup().get());
    }

    @Test
    public void checkText() throws Exception {

        assertEquals(RuntimeEnvironment.application.getString(R.string.activityMain_title),
                ((Toolbar)checkoutActivity.findViewById(R.id.vToolbar)).getTitle());
    }

}

Вуаля! В моем тесте я получил ресурсы контекста от RuntimeEnvironment и он прошел!

...