我已经尝试了一个星期。而且,我已经检索了所有可用的文章,但它们的实现或示例不完善或停止在Espresso测试的步骤中。
我的Android应用程序遵循MVP架构(并且是Java)
场景:[仅举一个例子]我有一个HomeActivity
,使用Dagger2获得了HomePresenter
。 (提供通过HomeModule
中的void inject(HomeActivity activity)
公开的HomeComponent
中的方法。
在我的HomeActivity
的espressoTest中,我想注入一个模拟礼物。我还没有通过AppModule
公开AppComponent
内部的依赖关系。网络上大多数示例都这样做(因此,他们只是创建一个新的testApplication然后执行Needfull)]
我不想使用productFlavours方式来注入或提供模拟类,因为它无法控制Mockito.when
方法。
所以基本上。我想注入一个模拟演示者,为了在espresso中进行单元测试,我可以在其中执行任何Mockito.when()
操作。
HomeComponent
@HomeScope
@Component(modules = HomeModule.class,dependencies = AppComponent.class)
public interface HomeComponent {
void inject(HomeActivity activity);
}
HomeModule
@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);
}
}
AppComponent
@Component(modules = {AppModule.class,RepositoryModule.class})
@AppScope
public interface AppComponent {
void inject(App app);
FlowsRepository flowRepository();
LoanRepository loanRepository();
UserRepository userRepository();
}
AppModule
@Module
public class AppModule {
private Context appContext;
public AppModule(@NonNull Context context) {
this.appContext = context;
}
@Provides
@AppScope
public Context context() {
return appContext;
}
}
App
component = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
component.inject(this);
HomeActivity
HomeComponent component = DaggerHomeComponent.builder()
.appComponent(((App) getApplication()).getComponent())
.homeModule(new HomeModule(this))
.build();
再次。在我的测试中(浓缩咖啡),我想注入Mockito的嘲笑的HomePresenter。所以我可以对我的观点进行单元测试。
所以您的问题是您需要创建一个模块来提供模拟演示者进行测试,而不是“真实的”演示者。
这里有一篇很好的文章:Testing with Dagger
解决该问题的关键是使用提供模拟Presenter的Dagger Module而不是HomeActivity
仪器化测试中的“真实”模型。
为此,需要执行以下两个额外操作。
在下面的示例中,我将使用Kotlin。
定义委托人接口:
interface HomeComponentBuilder { fun build(view: IHomeContract.View): HomeComponent }
将
HomeComponent
初始化从HomeActivity
移动到委托实现:class HomeComponentBuilderImpl constructor(private val app: App) : HomeComponentBuilder { override fun build(view: IHomeContract.View): HomeComponent = DaggerHomeComponent.builder() .homeModule(HomeModule(view)) .build() }
将委托置于应用程序“范围”中,以便您可以将其实现互换用于有条件的测试:
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)
对于仪器化测试,创建扩展
TestHomeComponent
的HomeComponent
:@HomeScope @Component(modules = [TestHomeModule::class]) interface TestHomeComponent : HomeComponent
TestHomeModule
提供模拟Presenter
@Module class TestHomeModule { @Provides fun providePresenter(): IHomeContract.Presenter = mock() }
剩下要做的就是创建一个测试委托实现
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() } ... }
其余为标准。创建一个使用
AndroidJUnitRunner
的自定义TestAppImpl
: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() } }
您可以在sample project中查看更多详细信息。