gpt4 book ai didi

android - PowerMock + Robolectric + Dagger2。第一部分

转载 作者:太空宇宙 更新时间:2023-11-03 13:51:11 26 4
gpt4 key购买 nike


这个问题是从 PowerMock + Robolectric + Dagger2 的第一部分创建的
所以我又有点。对不起。

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

  1. 安卓用户界面元素
  2. 一些逻辑
  3. 静态方法调用
  4. dagger2 依赖项


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

  1. 用于模拟 UI 元素的 Robolectric
  2. 用于逻辑测试的单元测试
  3. 用于静态方法模拟的 PowerMock

Robolectric + PowerMock 集成问题已知且解决方案已知 - https://github.com/robolectric/robolectric/wiki/Using-PowerMock
但是有了这个解决方案,dagger2 依赖项就会失败。

注意代码
我的自定义 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);
}

}

应用SIP:

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

}

应用组件:

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

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

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)

如果您在放置时更改机器人 Activity :

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

最佳答案

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

  1. 您的观点是做的/知道的太多了。我说的是 FileDownloaderManager 的知识以及如何获取依赖项的知识
  2. 由于您使用的是注入(inject),我会将静态函数包装到一个类中并注入(inject)它。编写/维护测试会容易得多
  3. 甚至 AppComponent 类的名称都表明它不应该知道如何注入(inject) View 。考虑作用域注入(inject)
  4. 一些具有applicationContext 的未成年人。为什么它是volatile,你希望它从非主线程访问吗?已经是 ApplicationSIP 为什么还需要玩应用程序上下文和转换?

终于有了答案。第一个堆栈跟踪表明 appContext 为空。因此,您的应用程序的 onCreate 未被调用。我没有看到 RobolectricUnitTestRunner 的代码,但我认为问题出在 PowerMock 的使用上。第二个堆栈跟踪证明了这一点。所以我会说答案是停止使用 PowerMock

关于android - PowerMock + Robolectric + Dagger2。第一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34692021/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com