Функциональное тестирование Android с помощью кинжала

Я пытаюсь проверить активность с помощью Mockito и Dagger. Мне удалось применить зависимости к Activity в моем приложении, но при тестировании Activity я не смог ввести макет в Activity. Должен ли я вводить Activity для тестирования или позволить getActivity() создать его?

public class MainActivityTest extends
    ActivityInstrumentationTestCase2<MainActivity> {

@Inject Engine engineMock;
private MainActivity mActivity;
private Button mLogoutBtn;


public MainActivityTest() {
    super(MainActivity.class);
}

@Override
protected void setUp() throws Exception {
    super.setUp();

    // Inject engineMock to test
    ObjectGraph.create(new TestModule()).inject(this);
}

@Override
protected void tearDown() {
    if (mActivity != null)
        mActivity.finish();
}

 @Module(
 includes = MainModule.class,
 entryPoints = MainActivityTest.class,
 overrides = true
 )

static class TestModule {
    @Provides
    @Singleton
    Engine provideEngine() {
        return mock(Engine.class);
    }
}

@UiThreadTest
public void testLogoutButton() {

    when(engineMock.isLoggedIn()).thenReturn(true);

    mActivity = getActivity();
    mLogoutBtn = (Button) mActivity.findViewById(R.id.logoutButton);

    // how to inject engineMock to Activity under test?
    ObjectGraph.create(new TestModule()).inject(this.mActivity);

    assertTrue(mLogoutBtn.isEnabled() == true);
}
}

Ответ 1

Я использую Mockito и Dagger для функционального тестирования. Основная концепция заключается в том, что ваш тестовый класс наследуется от ActivityUnitTestCase, а не ActivityInstrumentationTestCase2; последний метод суперкласса onStart() для жизненного цикла Activity блокирует вас, чтобы вы ввели ваши двойные зависимости теста, но с первым суперклассом вы можете обрабатывать жизненный цикл более мелкозернистым.

Вы можете увидеть мои рабочие примеры с помощью dagger-1.0.0 и mockito для тестирования действий и фрагментов в:

https://github.com/IIIRepublica/android-civicrm-test

Тестируемый проект находится в:

https://github.com/IIIRepublica/android-civicrm

Надеюсь, это поможет вам

Ответ 2

Я еще немного экспериментировал и обнаружил, что Кинжал не способен правильно создавать активность, когда он вводится для тестирования. В новой версии теста проходит testDoSomethingCalledOnEngine, но onCreate не вызывается в MainActivity. Второй тест testDoSomethingUI завершается с ошибкой, и на самом деле есть два экземпляра MainActivity, onCreate вызывается в другой экземпляр (созданный ActivityInstrumentationTestCase2, который я хочу), но не к другому. Может быть, разработчики на Square только подумали о тестировании Activites с Robolectric вместо тестирования на приборной панели Android?

public class MainActivityTest extends
    ActivityInstrumentationTestCase2<MainActivity> {

@Inject Engine engineMock;
@Inject MainActivity mActivity;

public MainActivityTest() {
    super(MainActivity.class);
}

@Override
protected void setUp() throws Exception {
    super.setUp();

    // Inject engineMock to test & Activity under test
    ObjectGraph.create(new TestModule()).inject(this);
}


 @Module(
 includes = MainModule.class,
 entryPoints = MainActivityTest.class,
 overrides = true
 )

static class TestModule {
    @Provides
    @Singleton
    Engine provideEngine() {
        return mock(Engine.class);
    }
}

public void testDoSomethingCalledOnEngine() {
    when(engineMock.isLoggedIn()).thenReturn(true);
    mActivity.onSomethingHappened();
    verify(engineMock).doSomething();
}

@UiThreadTest
public void testDoSomethingUI() {
    when(engineMock.isLoggedIn()).thenReturn(true);
    mActivity.onSomethingHappened();
    Button btn = (Button) mActivity.findViewById(R.id.logoutButton);
    String btnText = btn.getText().toString(); 
    assertTrue(btnText.equals("Log out"));  
}

}

Ответ 3

Я собрал все вместе и сделал демонстрационное приложение, которое показывает, как тестировать кинжал: https://github.com/vovkab/dagger-unit-test

Вот мой предыдущий ответ с более подробной информацией:
fooobar.com/info/301433/...