gpt4 book ai didi

android - 如何使用 Espresso 在 Instrumentation 测试中注入(inject) Mocked Presenter of Activity

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:41:31 27 4
gpt4 key购买 nike

我已经试了一个星期了。我已经抓取了所有可用的文章,但它们的实现或示例不尽如人意或停留在 Espresso 测试的步骤。

我的 Android 应用程序遵循 MVP 架构(并且是在 Java 中)

场景:[仅举一个例子]我有一个使用 Dagger2 获取 HomePresenterHomeActivity。 (在通过 HomeComponent 中的 void inject(HomeActivity activity) 公开的 HomeModule 中提供方法。

在我的 HomeActivity 的 espressoTest 中,我想注入(inject)一个 mockpresent。我没有通过 AppComponentAppModule 中公开此依赖项。网上的大多数例子都是这样做的(所以他们只是创建一个新的 testApplication 然后做需要的)

我不想使用 productFlavours 方式注入(inject)或提供模拟类,因为它无法让我控制 Mockito.when 方法。

所以基本上。我想注入(inject)一个 mockpresenter,为了在 espresso 中进行单元测试,我可以在其中执行任何 Mockito.when() 操作。

我的代码如下。

主页组件

@HomeScope
@Component(modules = HomeModule.class,dependencies = AppComponent.class)
public interface HomeComponent {
void inject(HomeActivity activity);
}

家庭模块

@Module
public class HomeModule {

private final IHomeContract.View view;

public HomeModule(IHomeContract.View view) {
this.view = view;
}

@Provides
@HomeScope
public IHomeContract.Presenter presenter(FlowsRepository flowsRepository, UserRepository userRepository, LoanRepository loanRepository) {
return new HomePresenter(view, flowsRepository, userRepository, loanRepository);
}

}

应用组件

@Component(modules = {AppModule.class,RepositoryModule.class})
@AppScope
public interface AppComponent {
void inject(App app);

FlowsRepository flowRepository();
LoanRepository loanRepository();
UserRepository userRepository();
}

应用模块

@Module
public class AppModule {
private Context appContext;

public AppModule(@NonNull Context context) {
this.appContext = context;
}

@Provides
@AppScope
public Context context() {
return appContext;
}
}

应用

component = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
component.inject(this);

主页 Activity

HomeComponent component = DaggerHomeComponent.builder()
.appComponent(((App) getApplication()).getComponent())
.homeModule(new HomeModule(this))
.build();

再来一次。在我的测试(espresso)中,我想注入(inject)一个由 Mockito 设置的 mockedHomePresenter。所以我可以对我的观点进行单元测试。

最佳答案

解决问题的关键点是有这样一个 Dagger 模块,它在 HomeActivity 的插桩测试中提供模拟 Presenter的“真正的”。

为此,需要完成以下 2 个额外操作(您可能还希望看到 example )。

  1. HomeActivityComponent 的实例化委托(delegate)给一些抽象。
  2. 在插桩测试中替换抽象的实现以提供模拟。

我将在下面的示例中使用 Kotlin

定义委托(delegate)接口(interface):

interface HomeComponentBuilder {
fun build(view: IHomeContract.View): HomeComponent
}

HomeComponent 初始化从 HomeActivity 移至委托(delegate)实现:

class HomeComponentBuilderImpl constructor(private val app: App) : HomeComponentBuilder {

override fun build(view: IHomeContract.View): HomeComponent =
DaggerHomeComponent.builder()
.homeModule(HomeModule(view))
.build()
}

使委托(delegate)处于应用程序“范围”中,以便您可以为仪器测试交换其实现:

interface App {
val homeComponentBuilder: HomeComponentBuilder
...
}

App 实现现在应该包含

class AppImpl : Application(), App {
override val homeComponentBuilder: HomeComponentBuilder by lazy {
HomeComponentBuilderImpl(this@AppImpl)
}
...
}

HomeActivity 中的组件初始化如下所示:

(application as App)
.homeComponentBuilder
.build(this)
.inject(this)

对于仪器测试,创建扩展 HomeComponentTestHomeComponent:

@HomeScope
@Component(modules = [TestHomeModule::class])
interface TestHomeComponent : HomeComponent

TestHomeModule 提供了一个模拟Presenter

@Module
class TestHomeModule {

@Provides
fun providePresenter(): IHomeContract.Presenter = mock()
}

剩下要做的就是进行测试委托(delegate)实现

class TestHomeComponentBuilderImpl : HomeComponentBuilder {
override fun build(view: IHomeContract.View): HomeComponent =
DaggerTestHomeComponent.builder()
.testTestHomeModule(TestHomeModule())
.build()
}

并在 TestAppImpl 中初始化它

class TestAppImpl : Application(), App {
override val homeComponentBuilder: HomeComponentBuilder by lazy {
TestHomeComponentBuilderImpl()
}
...
}

其余的都是标准的。创建一个使用 TestAppImpl 的自定义 AndroidJUnitRunner:

class TestAppRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application = Instrumentation.newApplication(TestAppImpl::class.java, context)
}

并将其添加到app模块build.gradle

defaultConfig {
testInstrumentationRunner "your.package.TestAppRunner"
...
}

使用示例:

@RunWith(AndroidJUnit4::class)
class HomeActivityTest {
private lateinit var mockPresenter: IHomeContract.Presenter

@get:Rule
val activityRule = ActivityTestRule(HomeActivity::class.java)

@Before
fun setUp() {
mockPresenter = activityRule.activity.presenter
}

@Test
fun activity_onCreate_presenter_should_onViewCreated() {
verify(mockPresenter).someMethod()
}
}

关于android - 如何使用 Espresso 在 Instrumentation 测试中注入(inject) Mocked Presenter of Activity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51110120/

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