简体   繁体   English

PowerMock + Robolectric +匕首2

[英]PowerMock + Robolectric + Dagger2


I test custom view class which contain: 我测试自定义视图类,其中包含:

  1. android ui elements android ui元素
  2. some logic 一些逻辑
  3. static methods callings 静态方法调用
  4. dagger2 dependencies dagger2依赖项

So i use next tools for testing 所以我用下一个工具进行测试

  1. Robolectric for UI elements mocking Robolectric用于UI元素模拟
  2. unit tests for logic testing 逻辑测试的单元测试
  3. PowerMock for static methods mocking PowerMock用于静态方法模拟

Robolectric + PowerMock integration problem is known and solution is known - https://github.com/robolectric/robolectric/wiki/Using-PowerMock Robolectric + PowerMock集成问题已知,解决方案已知-https: //github.com/robolectric/robolectric/wiki/Using-PowerMock
But with this solution dagger2 dependencies fail. 但是使用此解决方案,dagger2依赖关系失败。

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 error: In 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)

And there is one trouble yet. 还有一个麻烦。 Other tests with Robolectric and dagger2 dependencies are not working. 具有Robolectric和dagger2依赖项的其他测试无法正常工作。

ProgressDownloadViewTest_AudioType: 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);
            ...
        }

}

Exception: 例外:

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

Update 更新
Resolving in PowerMock + Robolectric + Dagger2. 解决PowerMock + Robolectric + Dagger2。 Part I 第一部分

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

Also

 ApplicationSIP.get().applicationComponent().inject(this);

I'm not sure what you are referring to as this 我不知道你指的是什么为this

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. 我看不到您在类中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)

I hope this helps to get you a little clearer. 我希望这有助于您更加清晰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM