2016-01-09 52 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我編輯過。那裏有很多。我建議你可以在這裏拿出你能發現的更清晰的問題。 –