如何使用Dagger模块和Robolectric在Activity onResume()上测试模拟交互?

ron*_*tho 5 java android unit-testing robolectric dagger

我正在使用Dagger进行依赖注入,它在我的应用程序中运行良好但我无法测试它.为了创建模块依赖图,我遵循了这种模式:https://github.com/pyricau/shipfaster/blob/master/src/main/java/com/squareup/shipfaster/common/ShipFasterApplication.java

现在,在我的MainActivity测试类中,我希望能够在调用Activity onResume()方法时验证与mock的交互.

这是班级:

@Config(emulateSdk = 18)
@RunWith(RobolectricDaggerTestRunner.class)
public class MainActivityTest extends TestCase {

    @Inject MainActivity sut;
    public @Mock MyObject mockMyObject;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        ObjectGraph.create(new TestModule()).inject(this);
    }

    @Test
    public void testThatMyActivityDelegatesDoSomethingToMyObject(){
        //init
        ActivityController<MainActivity> activityController = ActivityController.of(sut);

        //run
        activityController.create().start().resume();

        //verify
        Mockito.verify(mockMyObject).doSomething();
    }

    @Module(
            includes = {ActivityModule.class},
            injects = MainActivityTest.class,
            overrides = true,
            library = true
    )
    class TestModule {
        @Provides
        MyObject provideMyObject() {
            return mockMyObject;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

从我所看到的,该onCreate()方法被调用,但使用的是真实的实例myObject,而不是被模拟的实例.测试失败了"想要但未被调用 - 实际上,与这个模拟没有交互." 错误.

也许这是因为我尝试使用Robolectric创建的MainActivity与我的TestModule没有关联,因为它是在Application级别创建的,但是我设法通过在MainActivity上显式调用方法并放置myObject来使该测试通过. doSomething()在那里,但我需要的是测试Android生命周期调用.

关于如何设法测试这个的任何想法?

Woj*_*hKo 1

使用真实对象是因为我猜你ObjectGraphApplication类中进行了初始化。当您在((Application) getApplication()).inject(this)测试期间调用时,您使用的方法ObjectGraph与刚刚运行应用程序时的方法相同。

ObjectGraph在此测试中,您将使用 的模拟实例创建全新的MyObject。这个模拟仅被注入MainActivityTest,因为当MainActivity inject()调用 in 时,它使用ObjectGraphmade in Application

您可以做的是创建TestApplication类(它必须与您的类具有相同的包Application,但需要位于测试目录中),它扩展您的应用程序,并添加您TestModule以使用模拟覆盖真实实例。例如这样:

我的应用程序.java

package com.example.myapp;

public class MyApplication extends Application {

    ObjectGraph graph;
    private Account currentAccount;

    @Override
    public void onCreate() {
        super.onCreate();
        graph = ObjectGraph.create(getModules().toArray());
        init();
    }

    void init() {
        // initialization stuff should not be called in tests
    }

    List<Object> getModules() {
        List<Object> modules = new ArrayList<>();
        modules.add(new ActivityModule(this));
        return modules;
    }

    public void inject(Object object) {
        graph.inject(object);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试我的应用程序.java

package com.example.myapp;

public class TestMyApplication extends MyApplication {

    @Override
    void init() {

    }

    @Override
    List<Object> getModules() {
        modules = super.getModules();
        modules.add(new TestModule());
        return modules;
    }
}
Run Code Online (Sandbox Code Playgroud)