2016-01-09 31 views
2


I测试包含定制视图类:PowerMock + Robolectric + Dagger2

  1. 机器人UI元素
  2. 一些逻辑
  3. 静态方法召唤
  4. dagger2依赖性

所以我使用下一个测试工具

  1. Robolectric为嘲笑为逻辑测试
  2. 单元测试UI元素
  3. PowerMock静态方法嘲笑

Robolectric + 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:

 
@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); 
     } 

} 

在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) 

而且有一个麻烦呢。使用Robolectric和dagger2依赖项的其他测试不起作用。

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 : '[email protected]a22' 
    created class : 'com.tg.osip.tdclient.update_managers.FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05', loaded by classloader : '[email protected]a22' 
    proxy instance class : 'com.tg.osip.tdclient.update_managers.FileDownloaderManager$$EnhancerByMockitoWithCGLIB$$a751cd05', loaded by classloader : '[email protected]' 
    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. Part I

+0

我不打算试图通过所有这些代码,有太多。只输入相关的代码。 –

+0

@MsYvette,以便您可以观看ProgressTextView,ProgressTextViewText和ProgressTextViewTest错误。我离开其他班以防万一 –

+0

我不确定没有经历它,抱歉我也在工作,所以不能给它足够的时间。想想,这是另一个人了解我的问题的必要吗?太多的代码会让人们忽略它,这就是我的观点。 –

回答

0
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

我看不到你身在何处,你initialsing 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) 

我希望这有助于让你更清楚一点。

+0

我需要寻找类铸造异常挂在 –

+0

谢谢,我会尝试 –

+0

@ xoxol_89我编辑过。那里有很多。我建议你可以在这里拿出你能发现的更清晰的问题。 –