我测试自定义视图类,其中包含:
- android ui elements
- 一些逻辑
- 静态方法调用 <
- dagger2依赖/gh>
所以我使用next工具来测试
- Robolectric用于模拟UI元素
- 逻辑测试的单元测试 PowerMock用于静态方法模拟
robolelectric + PowerMock集成问题是已知的,解决方案是已知的- https://github.com/robolectric/robolectric/wiki/Using-PowerMock
但是这个解决方案dagger2依赖失败。
注意代码。
自定义视图:
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错误:
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)
还有一个麻烦。其他与robolelectric和dagger2相关的测试都不起作用。
ProgressDownloadViewTest_AudioType:
例外:
创建模拟代理时发生ClassCastException:要模拟的类:'com.tg.osip.tdclient.update_managers. 'FileDownloaderManager',由classloader加载:'org.robolectric.internal.bytecode.InstrumentingClassLoader@403f0a22'已创建类:'com.tg.osip.tdclient.update_managers. 'FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05',由classloader加载:'org.robolectric.internal.bytecode.InstrumentingClassLoader@403f0a22'代理实例类:'com.tg.osip.tdclient.update_managers. 'FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05',由classloader加载:'org.mockito.internal.creation.util.SearchingClassLoader@10bd9df0'由ObjenesisInstantiator创建实例你可能会遇到类加载问题,禁用Objenesis缓存*可能*有帮助(参见MockitoConfiguration)org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise (ClassImposterizer.java: 61)在org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise (ClassImposterizer.java: 49)在org.powermock.api.mockito.repackaged.CglibMockMaker.createMock (CglibMockMaker.java: 24)org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.createMock (PowerMockMaker.java: 45)com.tg.osip.ui.general.views.progress_download.ProgressDownloadViewTest_AudioType.setup (ProgressDownloadViewTest_AudioType.java: 46)在sun.reflect.NativeMethodAccessorImpl。invoke0(本地方法)sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java: 62)sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java: 43)org.junit.runners.model.FrameworkMethod runreflectivecall 1.美元(FrameworkMethod.java: 50)org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java: 12)在org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java: 47)在org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java: 24)org.robolectric.RobolectricTestRunner评估2.美元(RobolectricTestRunner.java: 251)org.robolectric.RobolectricTestRunner.runChild (RobolectricTestRunner.java: 188)org.robolectric.RobolectricTestRunner.runChild (RobolectricTestRunner.java: 54)在org.junit.runners.ParentRunner 3.美元运行(ParentRunner.java: 290)在org.junit.runners.ParentRunner 1.美元计划(ParentRunner.java: 71)org.junit.runners.ParentRunner.runChildren (ParentRunner.java: 288)org.junit.runners.ParentRunner.access 000美元(ParentRunner.java: 58)org.junit.runners.ParentRunner评估2.美元(ParentRunner.java: 268)org.robolectric.RobolectricTestRunner评估1.美元(RobolectricTestRunner.java: 152)org.junit.runners.ParentRunner.run (ParentRunner.java: 363)org.junit.runners.Suite.runChild (Suite.java: 128)在org.junit.runners.Suite.runChild (Suite.java: 27)在org.junit.runners.ParentRunner 3.美元运行(ParentRunner.java: 290)在org.junit.runners.ParentRunner 1.美元计划(ParentRunner.java: 71)org.junit.runners.ParentRunner.runChildren (ParentRunner.java: 288)org.junit.runners.ParentRunner.access 000美元(ParentRunner.java: 58)org.junit.runners.ParentRunner评估2.美元(ParentRunner.java: 268)org.junit.runners.ParentRunner.run (ParentRunner.java: 363)org.junit.runner.JUnitCore.run (JUnitCore.java: 137)com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs (JUnit4IdeaTestRunner.java: 78)com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart (JUnitStarter.java: 212)com.intellij.rt.execution.junit.JUnitStarter.main (JUnitStarter.java: 68)在sun.reflect.NativeMethodAccessorImpl。invoke0(本地方法)sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java: 62)com.intellij.rt.execution.application.AppMain.main (AppMain.java: 140)java.lang.ClassCastException: Cannot cast com.tg.osip.tdclient.update_managers。FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05到com.tg.osip.tdclient.update_managers.FileDownloaderManagerjava.lang.Class.cast (Class.java: 3369)org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise (ClassImposterizer.java: 59)在org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise (ClassImposterizer.java: 49)在org.powermock.api.mockito.repackaged.CglibMockMaker.createMock (CglibMockMaker.java: 24)org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.createMock (PowerMockMaker.java: 45)org.mockito.internal.util.MockUtil.createMock (MockUtil.java: 33)org.mockito.internal.MockitoCore.mock (MockitoCore.java: 59)org.mockito.Mockito.mock (Mockito.java: 1284)org.mockito.internal.configuration.MockAnnotationProcessor.process (MockAnnotationProcessor.java: 33)在org.mockito.internal.configuration.MockAnnotationProcessor.process (MockAnnotationProcessor.java: 16)org.mockito.internal.configuration.DefaultAnnotationEngine.createMockFor (DefaultAnnotationEngine.java: 43)org.mockito.internal.configuration.DefaultAnnotationEngine.process (DefaultAnnotationEngine.java: 66)org.mockito.internal.configuration.InjectingAnnotationEngine.processIndependentAnnotations (InjectingAnnotationEngine.java: 71)org.mockito.internal.configuration.InjectingAnnotationEngine.process (InjectingAnnotationEngine.java: 55)org.mockito.MockitoAnnotations.initMocks (MockitoAnnotations.java: 108)…36更多
更新
解析在PowerMock + robolelectric + 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);
}
你需要改变你的程序逻辑来允许这样的事情:
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管理器。
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)
我希望这能帮助你更清楚一点。