Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用Dagger模块和Robolectric在Activity onResume()上测试模拟交互?_Java_Android_Unit Testing_Robolectric_Dagger - Fatal编程技术网

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

Java 如何使用Dagger模块和Robolectric在Activity onResume()上测试模拟交互?,java,android,unit-testing,robolectric,dagger,Java,Android,Unit Testing,Robolectric,Dagger,我正在使用Dagger进行依赖注入,它在我的应用程序中运行良好,但我无法测试它。我遵循此模式创建模块依赖关系图: 现在,在我的MainActivity测试类中,我希望能够在调用Activity onResume()方法时验证与模拟的交互 下面是课堂: @Config(emulateSdk = 18) @RunWith(RobolectricDaggerTestRunner.class) public class MainActivityTest extends TestCase { @

我正在使用Dagger进行依赖注入,它在我的应用程序中运行良好,但我无法测试它。我遵循此模式创建模块依赖关系图:

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

下面是课堂:

@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;
        }
    }
}
@Config(emulateSdk=18)
@RunWith(RobolectrictDaggerTestRunner.class)
公共类MainActivityTest扩展了TestCase{
@注射主要活性sut;
public@Mock MyObject mockMyObject;
@以前
public void setUp()引发异常{
initMocks(this);
create(newtestmodule()).inject(this);
}
@试验
public void testThatMyActivityDelegatesDoSomethingToMyObject()的测试{
//初始化
ActivityController ActivityController=ActivityController.of(sut);
//跑
activityController.create().start().resume();
//核实
Mockito.verify(mockMyObject.doSomething();
}
@模块(
includes={ActivityModule.class},
injects=MainActivityTest.class,
覆盖=真,
库=真
)
类测试模块{
@提供
MyObject提供MyObject(){
返回mockMyObject;
}
}
}
据我所见,调用了
onCreate()
方法,但使用了
myObject
的真实实例,而不是模拟的实例。测试失败,出现“需要但未调用-实际上,与此模拟没有任何交互”错误

这可能是因为我尝试使用Robolectric创建的MainActivity与我的TestModule没有关联,因为它是在应用程序级别创建的,但我设法使该测试通过了对MainActivity的显式调用方法,并将myObject.doSomething()放在其中,但我需要的是测试Android生命周期调用


你知道我该如何测试这个吗

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

在本测试中,您将使用
MyObject
的模拟实例创建全新的
ObjectGraph
。此模拟仅在
MainActivityTest
中注入,因为在
MainActivity
中调用
inject()
时,它使用
应用程序中制作的
对象图

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

MyApplication.java
package com.example.myapp;
公共类MyApplication扩展了应用程序{
对象图;
私人账户;经常账户;
@凌驾
public void onCreate(){
super.onCreate();
graph=ObjectGraph.create(getModules().toArray());
init();
}
void init(){
//测试中不应调用初始化内容
}
列出getModules(){
列表模块=新的ArrayList();
添加(新活动模块(this));
返回模块;
}
公共无效注入(对象){
图形注入(对象);
}
}
TestMyApplication.java
package com.example.myapp;
公共类TestMyApplication扩展了MyApplication{
@凌驾
void init(){
}
@凌驾
列出getModules(){
modules=super.getModules();
modules.add(newtestmodule());
返回模块;
}
}

不久前,我也遇到了同样的问题,但我成功地解决了它,如下所示:

WojciechKo建议在某些情况下可能有效,但我的解决方案可以在测试中不重写应用程序类的情况下工作。区别在于,您仍然需要提供一种在应用程序中注入匕首模块的方法,而不是在应用程序类中实例化它们。这样,您可以在测试类中添加TestModule,以覆盖实际应用程序类中使用的模块


如果您对该链接中提供的解决方案有问题,请告诉我,我们可以进一步调查该问题。

您的
MainActivity sut
实例来自哪里?是否有其他模块提供此类?何时将
MyObject
实例注入
sut
?在上面的代码示例中,
MainActivity
是使用
@inject
注入的,它不是由任何模块提供的,dagger将只使用默认构造函数。我还尝试在我的
setup()
方法中创建它,只需执行
MainActivity sut=newmainActivity()
它没有任何区别。在MainActivity中,MyObject由Dagger注入:
public类MainActivity扩展了BaseActivity{@Inject MyObject MyObject;..
好的,我假设您的
MainActivity
构造函数上有
@Inject
注释。您具体在哪里将
MyObject
注入
MainActivity
?只要Dagger使用默认构造函数实例化对象,它就不会注入其字段。
 @Inject
不在构造函数中,而是在字段声明中。否,使用Dagger,您不需要专门将对象注入到活动中,Dagger会自动为您执行此操作。您需要做的唯一一件事是创建依赖关系图。我正在我的MainActivity
中的
onCreated()
方法中执行此操作((Application)getApplication()).inject(this);
。作为提醒,我的代码已完全更新
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);
    }
}
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;
    }
}