PowerMock + Robolectric +匕首2 [英] PowerMock + Robolectric + Dagger2
问题描述
我测试包含以下内容的自定义视图类:
I test custom view class which contain:
- android ui元素
- 一些逻辑
- 静态方法调用
- dagger2依赖项
- android ui elements
- some logic
- static methods callings
- dagger2 dependencies
所以我使用下一个工具进行测试
So i use next tools for testing
- Robolectric用于模拟UI元素
- 用于逻辑测试的单元测试
- 用于静态方法模拟的PowerMock
Robolectric + PowerMock集成问题已知,解决方案已知- https://github.com/robolectric/robolectric/ wiki / Using-PowerMock
但是使用此解决方案,dagger2依赖项失败。
注意编码。
我的自定义视图:
Robolectric + PowerMock integration problem is known and solution is known - https://github.com/robolectric/robolectric/wiki/Using-PowerMock
But with this solution dagger2 dependencies fail.
Attention to code.
My custom view:
public class ProgressTextView extends TextView {
private String defaultText;
private int fileSize;
private String fileSizeString;
private FileDownloaderI fileDownloader;
@Inject
FileDownloaderManager fileDownloaderManager;
Subscription downloadProgressChannelSubscription;
Subscription downloadCancelChannelSubscription;
public ProgressTextView(Context context) {
super(context);
provideDependency();
}
public ProgressTextView(Context context, AttributeSet attrs) {
super(context, attrs);
provideDependency();
}
public ProgressTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
provideDependency();
}
private void provideDependency() {
ApplicationSIP.get().applicationComponent().inject(this);
}
}
ProgressTextViewTest:
ProgressTextViewTest:
@RunWith(RobolectricUnitTestRunner.class)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
@PrepareForTest(Formatter.class)
public class ProgressTextViewTest {
Activity activity;
@Mock
FileDownloaderManager fileDownloaderManager;
@Rule
public PowerMockRule rule = new PowerMockRule();
@Before
public void beforeTest() {
// PowerMockito
PowerMockito.mockStatic(Formatter.class);
when(Formatter.formatFileSize(anyObject(), anyInt())).thenReturn("");
// Mockito
MockitoAnnotations.initMocks(this);
// Robolectic
activity = Robolectric.setupActivity(Activity.class);
}
@Test
public void init_FileDownloaded() {
ProgressTextView progressTextView = new ProgressTextView(activity);
}
}
In ProgressTextViewTest错误:
In ProgressTextViewTest error:
java.lang.NullPointerException
at com.tg.osip.ApplicationSIP.get(ApplicationSIP.java:64)
at com.tg.osip.ui.general.views.ProgressTextView.provideDependency(ProgressTextView.java:56)
at com.tg.osip.ui.general.views.ProgressTextView.<init>(ProgressTextView.java:42)
at com.tg.osip.ui.general.views.ProgressTextViewTest.init_FileDownloaded(ProgressTextViewTest.java:72)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1873)
at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:773)
at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:638)
at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:98)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78)
at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
有一个麻烦了。其他具有Robolectric和dagger2依赖项的测试无法正常工作。
ProgressDownloadViewTest_AudioType:
And there is one trouble yet. Other tests with Robolectric and dagger2 dependencies are not working.
ProgressDownloadViewTest_AudioType:
@RunWith(RobolectricUnitTestRunner.class)
public class ProgressDownloadViewTest_AudioType {
Activity activity;
@Mock
FileDownloaderManager fileDownloaderManager;
@Mock
MediaManager mediaManager;
@Before
public void setup() {
// Mockito
MockitoAnnotations.initMocks(this);
// Robolectic
activity = Robolectric.setupActivity(Activity.class);
}
@Test
public void setDownloadingState_emptyFileDownloaderI() {
ProgressDownloadView progressDownloadView = new ProgressDownloadView(activity, ProgressDownloadView.Type.AUDIO);
...
}
}
例外:
ClassCastException occurred while creating the mockito proxy :
class to mock : 'com.tg.osip.tdclient.update_managers.FileDownloaderManager', loaded by classloader : 'org.robolectric.internal.bytecode.InstrumentingClassLoader@403f0a22'
created class : 'com.tg.osip.tdclient.update_managers.FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05', loaded by classloader : 'org.robolectric.internal.bytecode.InstrumentingClassLoader@403f0a22'
proxy instance class : 'com.tg.osip.tdclient.update_managers.FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05', loaded by classloader : 'org.mockito.internal.creation.util.SearchingClassLoader@10bd9df0'
instance creation by : ObjenesisInstantiator
You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)
at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:61)
at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:49)
at org.powermock.api.mockito.repackaged.CglibMockMaker.createMock(CglibMockMaker.java:24)
at org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.createMock(PowerMockMaker.java:45)
at com.tg.osip.ui.general.views.progress_download.ProgressDownloadViewTest_AudioType.setup(ProgressDownloadViewTest_AudioType.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ClassCastException: Cannot cast com.tg.osip.tdclient.update_managers.FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05 to com.tg.osip.tdclient.update_managers.FileDownloaderManager
at java.lang.Class.cast(Class.java:3369)
at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:59)
at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:49)
at org.powermock.api.mockito.repackaged.CglibMockMaker.createMock(CglibMockMaker.java:24)
at org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.createMock(PowerMockMaker.java:45)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
at org.mockito.Mockito.mock(Mockito.java:1284)
at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:33)
at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:16)
at org.mockito.internal.configuration.DefaultAnnotationEngine.createMockFor(DefaultAnnotationEngine.java:43)
at org.mockito.internal.configuration.DefaultAnnotationEngine.process(DefaultAnnotationEngine.java:66)
at org.mockito.internal.configuration.InjectingAnnotationEngine.processIndependentAnnotations(InjectingAnnotationEngine.java:71)
at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:55)
at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108)
... 36 more
更新
解决 PowerMock + Robolectric + Dagger2。第一部分
推荐答案
Activity activity;
@Mock
FileDownloaderManager fileDownloaderManager;
@Rule
public PowerMockRule rule = new PowerMockRule();
@Before
public void beforeTest() {
// You intialise activity here
activity = Robolectric.setupActivity(Activity.class);
}
@Test
public void init_FileDownloaded() {
// and use it here, the initialisation is out of scope for this
ProgressTextView progressTextView = new ProgressTextView(activity);
}
您需要更改程序逻辑以允许如下所示:
You need to change your program logic to allow for something like this:
Activity activity;
@Mock
FileDownloaderManager fileDownloaderManager;
activity = Robolectric.setupActivity(Activity.class);
@Rule
public PowerMockRule rule = new PowerMockRule();
@Before
public void beforeTest() {
}
@Test
public void init_FileDownloaded() {
ProgressTextView progressTextView = new ProgressTextView(activity);
}
也
ApplicationSIP.get().applicationComponent().inject(this);
我不确定您指的是 this
我看不到您在类中初始化 FileDownloaderManager
的位置,但看来您正在尝试将自定义管理器用作内置的android管理器。
I cannot see where you are initialsing FileDownloaderManager
in you classes, but it seems you are attempting to use the custom manager as the inbuilt android manager.
Caused by: java.lang.ClassCastException: Cannot cast com.tg.osip.tdclient.update_managers.FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05 to com.tg.osip.tdclient.update_managers.FileDownloaderManager
at java.lang.Class.cast(Class.java:3369)
我希望这有助于使您更加清晰。
I hope this helps to get you a little clearer.
这篇关于PowerMock + Robolectric +匕首2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!