PowerMock + Robolectric + Dagger2。第一部分 [英] PowerMock + Robolectric + Dagger2. Part I

查看:105
本文介绍了PowerMock + Robolectric + Dagger2。第一部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



这个问题是从 PowerMock + Robolectric + Dagger2 的第一部分创建的。 a>

所以我又有点。抱歉。


我测试了包含以下内容的自定义视图类:


This question was created from first part of PowerMock + Robolectric + Dagger2
So i'm a little bit again. Sorry.

I test custom view class which contain:


  1. android ui元素

  2. 一些逻辑

  3. 静态方法调用

  4. dagger2依赖项

  1. android ui elements
  2. some logic
  3. static methods callings
  4. dagger2 dependencies



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


So i use next tools for testing


  1. Robolectric用于UI元素模拟

  2. 用于逻辑测试的单元测试

  3. 用于模拟
    的静态方法的PowerMock

Robolectric + PowerMock集成问题已知并且解决方案已知- https://github.com/robolectric/robolectric/wiki/Using-PowerMock

但是有了这个解决方案dagger2依赖项失败。




注意编码

我的自定义视图- ProgressTextView

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 - ProgressTextView:

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

}

ApplicationSIP

public class ApplicationSIP extends Application {

    public static volatile Context applicationContext;

    @NonNull
    private AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        applicationContext = getApplicationContext();
        Logger.registerLogger(this);

        appComponent = prepareApplicationComponent().build();
        appComponent.inject(this);
    }

    @NonNull
    protected DaggerAppComponent.Builder prepareApplicationComponent() {
        return DaggerAppComponent.builder()
                .appModule(new AppModule(getApplicationContext()))
                .tGModule(new TGModule());
    }

    @NonNull
    public AppComponent applicationComponent() {
        return appComponent;
    }

    @NonNull
    public static ApplicationSIP get() {
        return (ApplicationSIP) applicationContext.getApplicationContext();
    }

}

AppComponent

@Component(modules = {AppModule.class, TGModule.class, MediaModule.class, StaticModule.class})
@Singleton
public interface AppComponent {   
    void inject(ApplicationSIP applicationSIP);
    void inject(ProgressDownloadView progressDownloadView);
    void inject(ProgressTextView progressTextView);
}

ProgressTextViewTest

@RunWith(RobolectricUnitTestRunner.class)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
@PrepareForTest(Formatter.class)
public class ProgressTextViewTest {

    @Rule
    public PowerMockRule rule = new PowerMockRule();
    Activity activity;

    @Before
    public void beforeTest() {
        // PowerMockito
        PowerMockito.mockStatic(Formatter.class);
        Mockito.when(Formatter.formatFileSize(anyObject(), anyInt())).thenReturn("");
        // Robolectic
        activity = Robolectric.setupActivity(Activity.class);
    }

    @Test
    public void init_FileDownloaded() {
        ProgressTextView progressTextView = new ProgressTextView(activity);
        ...
    }
}

所以当我开始时此测试我得到下一个异常:

So when i start this test i get next exception:

java.lang.NullPointerException
at com.tg.osip.ApplicationSIP.get(ApplicationSIP.java:64)
at com.tg.osip.ui.general.views.ProgressTextView.provideDependency(ProgressTextView.java:60)
at com.tg.osip.ui.general.views.ProgressTextView.<init>(ProgressTextView.java:46)
at com.tg.osip.ui.general.views.ProgressTextViewTest.init_FileDownloaded(ProgressTextViewTest.java:67)
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.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)

如果您更改了机器人活动的初始放置:

If you change robolectric activity init placing:

@RunWith(RobolectricUnitTestRunner.class)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
@PrepareForTest(Formatter.class)
public class ProgressTextViewTest {

    @Rule
    public PowerMockRule rule = new PowerMockRule();
    Activity activity = Robolectric.setupActivity(Activity.class);

    @Before
    public void beforeTest() {
        // PowerMockito
        PowerMockito.mockStatic(Formatter.class);
        Mockito.when(Formatter.formatFileSize(anyObject(), anyInt())).thenReturn("");
    }

    @Test
    public void init_FileDownloaded() {
        ProgressTextView progressTextView = new ProgressTextView(activity);
        ...
    }
}

我得到其他例外:

java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:569)
at java.lang.StringBuffer.append(StringBuffer.java:369)
at java.io.StringWriter.write(StringWriter.java:94)
at com.thoughtworks.xstream.core.util.QuickWriter.flush(QuickWriter.java:73)
at com.thoughtworks.xstream.io.xml.PrettyPrintWriter.flush(PrettyPrintWriter.java:342)
at com.thoughtworks.xstream.XStream.toXML(XStream.java:858)
at com.thoughtworks.xstream.XStream.toXML(XStream.java:843)
at org.powermock.classloading.DeepCloner.clone(DeepCloner.java:53)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:89)
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.runner.JUnitCore.run(JUnitCore.java:137)
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 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)


推荐答案

在回答您的问题之前。我会说:

Before answering your question. I would say:


  1. 您的视图做的太多/知道的太多。我在谈论 FileDownloaderManager 的知识和关于如何获取依赖项的知识

  2. 由于您正在使用注入,因此我会包装静态函数上课并注入。编写/维护测试会容易得多

  3. 甚至类 AppComponent 的名称都说,它不应该知道如何注入视图。考虑一下范围内的注入

  4. 一些具有 applicationContext 的未成年人。为什么它是 volatile ,您是否希望从非主线程访问它? ApplicationSIP 为什么您需要玩应用程序上下文和强制转换?

  1. Your view is doing/knowing too much. I'm talking about knowledge of FileDownloaderManager and knowledge about how to get dependencies
  2. Since you're using injection I would wrap static functions into a class and inject it. It will be much easier to write/maintain tests
  3. Even name of class AppComponent says that it should not know about how to inject a view. Think about scoped injections
  4. Some minors with applicationContext. Why it is volatile, do you expect it to be accessed from non-main thread? It is already ApplicationSIP why do you need play with application context and casting?

最后回答。第一个堆栈跟踪显示 appContext 为空。因此未调用您应用的 onCreate 。我没有看到 RobolectricUnitTestRunner 的代码,但我认为问题出在 PowerMock 的使用上。第二个堆栈跟踪那种证明。因此,我想说的答案是停止使用 PowerMock

Finally to the answer. The first stack trace says that the appContext is null. So onCreate of your app was not called. I don't see the code of RobolectricUnitTestRunner but I assume the problem is in the usage of the PowerMock. The second stack trace kind of proof for that. So I would say the answer is to stop usage of the PowerMock.

这篇关于PowerMock + Robolectric + Dagger2。第一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆