yUd*_*Dis 6 tdd android android-espresso dagger-2 android-mvp
我已经尝试了一个星期.我已经抓取了所有可用的文章,但他们的实现或示例不足或停止在Espresso测试的步骤.
我的Android应用程序遵循MVP架构(并且是Java)
场景:[仅举一个例子]我有HomeActivity一个HomePresenter使用Dagger2.(提供方法在HomeModule通过a void inject(HomeActivity activity)中暴露出来HomeComponent.
在我的espressoTest中,HomeActivity我想注入一个模拟演示.我还没有暴露内部的这种依赖性AppModule通过AppComponent.网上的大多数例子都是这样的(所以他们只是创建一个新的testApplication然后做必要的)
我不想使用productFlavours注入或提供模拟类的方式,因为它不能让我控制Mockito.when方法.
所以基本上.我想注入一个mockpresenter,我可以做任何Mockito.when()事情,为了我的浓缩咖啡单位测试.
HomeComponent
@HomeScope
@Component(modules = HomeModule.class,dependencies = AppComponent.class)
public interface HomeComponent {
void inject(HomeActivity activity);
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
AppComponent
@Component(modules = {AppModule.class,RepositoryModule.class})
@AppScope
public interface AppComponent {
void inject(App app);
FlowsRepository flowRepository();
LoanRepository loanRepository();
UserRepository userRepository();
}
Run Code Online (Sandbox Code Playgroud)
的AppModule
@Module
public class AppModule {
private Context appContext;
public AppModule(@NonNull Context context) {
this.appContext = context;
}
@Provides
@AppScope
public Context context() {
return appContext;
}
}
Run Code Online (Sandbox Code Playgroud)
应用
component = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
component.inject(this);
Run Code Online (Sandbox Code Playgroud)
HomeActivity
HomeComponent component = DaggerHomeComponent.builder()
.appComponent(((App) getApplication()).getComponent())
.homeModule(new HomeModule(this))
.build();
Run Code Online (Sandbox Code Playgroud)
再来一次.在我的测试中(espresso)我想注入一个模拟的HomePresenter,由Mockito设置.所以我可以单独测试我的观点.
解决这个问题的关键是要有这样一个Dagger 模块,它在的仪器测试中提供一个模拟PresenterHomeActivity而不是“真实”的。
为此,需要执行以下 2 个额外操作(您可能还想查看示例)。
我将在下面的示例中使用Kotlin。
定义委托接口:
interface HomeComponentBuilder {
fun build(view: IHomeContract.View): HomeComponent
}
Run Code Online (Sandbox Code Playgroud)
将HomeComponent初始化从HomeActivity委托实现移到:
class HomeComponentBuilderImpl constructor(private val app: App) : HomeComponentBuilder {
override fun build(view: IHomeContract.View): HomeComponent =
DaggerHomeComponent.builder()
.homeModule(HomeModule(view))
.build()
}
Run Code Online (Sandbox Code Playgroud)
使委托位于应用程序“范围”中,以便您可以将其实现交换为已检测的测试:
interface App {
val homeComponentBuilder: HomeComponentBuilder
...
}
Run Code Online (Sandbox Code Playgroud)
App 实现现在应该包含
class AppImpl : Application(), App {
override val homeComponentBuilder: HomeComponentBuilder by lazy {
HomeComponentBuilderImpl(this@AppImpl)
}
...
}
Run Code Online (Sandbox Code Playgroud)
组件初始化HomeActivity如下:
(application as App)
.homeComponentBuilder
.build(this)
.inject(this)
Run Code Online (Sandbox Code Playgroud)
对于仪器测试创建TestHomeComponent扩展HomeComponent:
@HomeScope
@Component(modules = [TestHomeModule::class])
interface TestHomeComponent : HomeComponent
Run Code Online (Sandbox Code Playgroud)
whereTestHomeModule提供了一个模拟Presenter
@Module
class TestHomeModule {
@Provides
fun providePresenter(): IHomeContract.Presenter = mock()
}
Run Code Online (Sandbox Code Playgroud)
剩下要做的是进行测试委托实现
class TestHomeComponentBuilderImpl : HomeComponentBuilder {
override fun build(view: IHomeContract.View): HomeComponent =
DaggerTestHomeComponent.builder()
.testTestHomeModule(TestHomeModule())
.build()
}
Run Code Online (Sandbox Code Playgroud)
并初始化它 TestAppImpl
class TestAppImpl : Application(), App {
override val homeComponentBuilder: HomeComponentBuilder by lazy {
TestHomeComponentBuilderImpl()
}
...
}
Run Code Online (Sandbox Code Playgroud)
其余为标准。创建一个AndroidJUnitRunner使用的自定义TestAppImpl:
class TestAppRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application = Instrumentation.newApplication(TestAppImpl::class.java, context)
}
Run Code Online (Sandbox Code Playgroud)
并将其添加到app模块build.gradle
defaultConfig {
testInstrumentationRunner "your.package.TestAppRunner"
...
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
@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()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
321 次 |
| 最近记录: |