gpt4 book ai didi

android - 使用 Robolectric 和 Mockito 对 Realm + Dagger 2 进行单元测试

转载 作者:行者123 更新时间:2023-11-29 15:42:27 24 4
gpt4 key购买 nike

所以我正在开发这个使用 Dagger 2 进行依赖注入(inject)并将 Realm 作为数据库的小项目。

我正在使用 Robolectric 和 Mockito(使用 Powermock)对其进行单元测试。从之前的研究(和很多痛苦)中,我意识到测试 Realm 非常费力,但过去已经完成了 here .

现在,我的项目的设置和结构与上面链接的项目非常相似。

当我运行我的单元测试时,所有测试都通过了,除了给我一条非常神秘的消息,如下所示:

java.lang.NullPointerException
at org.robolectric.internal.ShadowExtractor.extract(ShadowExtractor.java:5)
at org.robolectric.Shadows.shadowOf(Shadows.java:1190)
at org.robolectric.shadows.CoreShadowsAdapter.getMainLooper(CoreShadowsAdapter.java:37)
at org.robolectric.util.ComponentController.<init>(ComponentController.java:31)
at org.robolectric.util.ComponentController.<init>(ComponentController.java:23)
at org.robolectric.util.ActivityController.<init>(ActivityController.java:40)
at org.robolectric.util.ActivityController.of(ActivityController.java:32)
at org.robolectric.Robolectric.buildActivity(Robolectric.java:82)
at org.robolectric.Robolectric.buildActivity(Robolectric.java:78)
at org.robolectric.Robolectric.setupActivity(Robolectric.java:86)
at uk.co.placona.tradesafe.view.EditActivityTest.ActivityShouldNotBeNull(EditActivityTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.powermock.modules.junit4.internal.impl

上述错误指定的代码行是:

activity = Robolectric.setupActivity(EditActivity.class);

Activity 存在,并在启动时注入(inject)了一个 TradeRepository。

可以找到有问题的 Activity here连同其余的代码。我一直在尝试调试它大约 3 天,但没有成功。我创建的所有其他单元测试都运行良好,但 Activity 使用的任何单元测试除外,这让我觉得我可能遗漏了一些非常明显的东西。

很乐意在这里澄清任何问题。非常感谢!

最佳答案

static 是邪恶的,powermock 是邪恶的 :).

我认为你应该摆脱你的类注入(inject)器。您不需要它,因为您在应用程序的生命周期内只有一个 CustomApplication 对象。

你应该修改你的代码如下:

在 CustomApplication.java 中,创建应用程序组件,在字段变量中设置并注入(inject)

private ApplicationComponent applicationComponent;

public void setup(){
getOrCreateApplicationComponent().inject(this);
databaseRealm.setup();
stethoDebug.setup(this);
}

public ApplicationComponent getOrCreateApplicationComponent() {
if (applicationComponent == null) {
applicationComponent = DaggerApplicationComponent.builder()
.applicationContextModule(new ApplicationContextModule(this))
.repositoryModule(new RepositoryModule())
.build();
}

return applicationComponent;
}

CreateActivity、EditActivity、MainActivity的onCreate方法中,Injector替换为

    ((CustomApplication) getApplication())
.getOrCreateApplicationComponent()
.inject(this);

在 RepositoryModule 中,我们将使用 Dagger 2 将依赖项注入(inject)构造函数,因此我们无需手动注入(inject) Context 和 DatabaseRealm

@Provides
@Singleton
public TradeRepository provideTradeRepository(DatabaseRealm databaseRealm) {
return new TradeRepositoryImpl(databaseRealm);
}

@Provides
@Singleton
public DatabaseRealm provideDatabaseRealm(Context context) {
return new DatabaseRealm(context);
}

然后在 DatabaseRealm 中我们添加一个以 Context 作为参数的构造函数

Context mContext;

RealmConfiguration realmConfiguration;

public DatabaseRealm(Context context) {
mContext = context;
}

和TradeRepositoryImpl一样,添加了一个带有databaseRealm的构造函数

DatabaseRealm databaseRealm;

public TradeRepositoryImpl(DatabaseRealm databaseRealm) {
this.databaseRealm = databaseRealm;
}

对于 RepositoryTestModule,我们添加 databaseRealm 作为参数:

@Provides
@Singleton
public TradeRepository provideTradeRepository(DatabaseRealm databaseRealm) {
return isMocked ? mock(TradeRepository.class) : new TradeRepositoryImpl(databaseRealm);
}

在您的 TestCustomApplication 中,我们覆盖了 getOrCreateApplicationComponent

@Override
public ApplicationComponent getOrCreateApplicationComponent() {
return DaggerApplicationComponentTest.builder()
.applicationContextModuleTest(new ApplicationContextModuleTest())
.repositoryModuleTest(new RepositoryModuleTest(false))
.build();
}

现在对于您的每个测试,我们使用 RobolectricGradleTestRunner 运行它们并添加 TestCustomApplication.class 作为应用程序标签

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21, application = TestCustomApplication.class)

当我们需要将依赖项注入(inject)我们的测试时,我们将像这样注入(inject):

@Before
public void setupDagger() {
DaggerApplicationComponentTest.builder()
.applicationContextModuleTest(new ApplicationContextModuleTest())
.repositoryModuleTest(new RepositoryModuleTest(false))
.build().inject(this);
}

我们的 EditActivityTest 中仍然有一个 NullPointerException,因为这一行:

loadTrade(intent.getExtras().getString("ID"));

要么检查 Intent 不为空,要么在测试中提供一个。

关于android - 使用 Robolectric 和 Mockito 对 Realm + Dagger 2 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38310175/

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