PowerMock + Robolectric + Dagger2。第一部分

编程入门 行业动态 更新时间:2024-10-19 16:36:38
本文介绍了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:

  • android ui元素
  • 一些逻辑
  • 静态方法调用
  • dagger2依赖项
  • android ui elements
  • some logic
  • static methods callings
  • dagger2 dependencies
  • 所以我使用下一个工具进行测试

    So i use next tools for testing

  • Robolectric用于UI元素模拟
  • 用于逻辑测试的单元测试
  • 用于模拟的静态方法的PowerMock
  • Robolectric + PowerMock集成问题已知并且解决方案已知- github/robolectric/robolectric/wiki/Using-PowerMock 但是有了这个解决方案dagger2依赖项失败。 注意编码 我的自定义视图- ProgressTextView :

    Robolectric + PowerMock integration problem is known and solution is known - github/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:

  • 您的视图做的太多/知道的太多。我在谈论 FileDownloaderManager 的知识和关于如何获取依赖项的知识
  • 由于您正在使用注入,因此我会包装静态函数上课并注入。编写/维护测试会容易得多
  • 甚至类 AppComponent 的名称都说,它不应该知道如何注入视图。考虑一下范围内的注入
  • 一些具有 applicationContext 的未成年人。为什么它是 volatile ,您是否希望从非主线程访问它? ApplicationSIP 为什么您需要玩应用程序上下文和强制转换?
  • Your view is doing/knowing too much. I'm talking about knowledge of FileDownloaderManager and knowledge about how to get dependencies
  • 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
  • Even name of class AppComponent says that it should not know about how to inject a view. Think about scoped injections
  • 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。第一部分

    本文发布于:2023-10-31 04:27:50,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1545000.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:第一部分   PowerMock   Robolectric

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!