[英]How to test mock interaction on Activity onResume() Using Dagger Modules and Robolectric?
I'm using Dagger for my dependency injection, it works well in my app but I have trouble to test it. 我正在使用Dagger进行依赖注入,它在我的应用程序中运行良好但我无法测试它。 I've followed this pattern in order to create the modules depenency graph : https://github.com/pyricau/shipfaster/blob/master/src/main/java/com/squareup/shipfaster/common/ShipFasterApplication.java
为了创建模块依赖图,我遵循了这种模式: https : //github.com/pyricau/shipfaster/blob/master/src/main/java/com/squareup/shipfaster/common/ShipFasterApplication.java
Now, in my MainActivity test class, I want to be able to verify interaction with a mock when the Activity onResume() method is called. 现在,在我的MainActivity测试类中,我希望能够在调用Activity onResume()方法时验证与mock的交互。
Here is the class : 这是班级:
@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;
}
}
}
From what I can see, the onCreate()
method is called but a real instance of myObject
is used, not the mocked one. 从我所看到的,调用
onCreate()
方法,但使用myObject
的真实实例,而不是myObject
实例。 The test failed with a "wanted but not invoked - Actually, there were zero interactions with this mock." 测试失败了“想要但未被调用 - 实际上,与这个模拟没有交互。” error.
错误。
Maybe this is because the MainActivity I'm trying to create using Robolectric is not associated with my TestModule because it's created in the Application level, but I manage to make that test to pass by explicitly call a method on the MainActivity and put the myObject.doSomething() in there, but what I need is to test Android lifecycle calls. 也许这是因为我试图使用Robolectric创建的MainActivity与我的TestModule没有关联,因为它是在应用程序级别创建的,但我设法通过在MainActivity上显式调用方法并放置myObject来使该测试通过。 doSomething()在那里,但我需要的是测试Android生命周期调用。
Any idea on how can I manage to test this? 关于如何设法测试这个的任何想法?
The real object is used because I guess you have initialization of ObjectGraph
in your Application
class. 使用真实对象是因为我猜你在
Application
类中初始化了ObjectGraph
。 When you call ((Application) getApplication()).inject(this)
during tests you are using the same ObjectGraph
as when you just run your application. 当您调用
((Application) getApplication()).inject(this)
在测试期间((Application) getApplication()).inject(this)
时,您使用与运行应用程序时相同的ObjectGraph
。
In this test you are creating completly new ObjectGraph
with mock instance of MyObject
. 在这个测试中,您将使用
MyObject
模拟实例创建完全新的ObjectGraph
。 This mock is injected only in MainActivityTest
because when in MainActivity
inject()
is called it uses ObjectGraph
made in Application
. 此模拟仅在
MainActivityTest
注入,因为在MainActivity
中调用inject()
时,它使用在Application
ObjectGraph
。
What you can do is to make TestApplication
class (it has to have the same package as your Application
class but needs to be in test directory) whitch extends your application and there add your TestModule
to override real instances with mocks. 您可以做的是创建
TestApplication
类(它必须与您的Application
类具有相同的包但需要在测试目录中),这会扩展您的应用程序并添加您的TestModule
以覆盖具有模拟的实例。 For example in this way: 例如,以这种方式:
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;
}
}
I had the same problems some time ago but I managed to solve it like this: Android Testing with Robolectric and Dagger 我前段时间遇到了同样的问题,但我设法解决了这个问题: 使用Robolectric和Dagger进行Android测试
WojciechKo suggestion may work in some cases but my solution can work without overriding the Application class in your tests.The difference is that you still need to provide a way to inject Dagger modules in your application rather than instantiating them in the Application class. WojciechKo建议可能在某些情况下有效但我的解决方案可以在您的测试中不覆盖Application类的情况下工作。区别在于您仍然需要提供一种方法来在应用程序中注入Dagger模块,而不是在Application类中实例化它们。 This way, in your test class you can add the TestModule to override the one that is used in the real Application class.
这样,在测试类中,您可以添加TestModule来覆盖真实Application类中使用的那个。
If you have problems with the solution presented in that link let me know and we can further investigate the problem. 如果您对该链接中提供的解决方案有疑问,请告知我们,我们可以进一步调查此问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.