- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我已经试了一个星期了。我已经抓取了所有可用的文章,但它们的实现或示例不尽如人意或停留在 Espresso 测试的步骤。
我的 Android 应用程序遵循 MVP 架构(并且是在 Java 中)
场景:[仅举一个例子]我有一个使用 Dagger2 获取 HomePresenter
的 HomeActivity
。 (在通过 HomeComponent
中的 void inject(HomeActivity activity)
公开的 HomeModule
中提供方法。
在我的 HomeActivity
的 espressoTest 中,我想注入(inject)一个 mockpresent。我没有通过 AppComponent
在 AppModule
中公开此依赖项。网上的大多数例子都是这样做的(所以他们只是创建一个新的 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 )。
我将在下面的示例中使用 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)
对于仪器测试,创建扩展 HomeComponent
的 TestHomeComponent
:
@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/
let appDelegate = UIKit.UIApplication.shared.delegate! if let tabBarController = appDelegate
我的演示文稿终于成功了。我的第一个屏幕有一个主要的 activity,第二个屏幕有一个 Presentation。我的问题是,我无法更改演示 View 中的内容。 为什么我不能在第二个屏幕上显示演示文
这个问题在这里已经有了答案: ios, getting a pointer to a controller from a view (5 个答案) 关闭 4 年前。 我有一个 uiview 文件,我
我有一个表示小部件的 View 类和一个随附的演示者类。我还有一个 View 类,用于拥有小部件的窗口,以及窗口 View 的随附演示者。窗口操作小部件,所以我需要窗口展示器与小部件展示器进行通信。可
关闭相机后。它给了我这个警告:在演示过程中尝试继续演示! - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picke
由于这个错误,我无法切换到另一个 View Controller 。我想在成功扫描二维码后切换到另一个 View Controller 。 2015-01-27 17:59:16.093 *[5416
有时它会发生 - 从代码的不同地方 - 我们想要做 UIViewController.presentViewController(a, b, c),有时我们已经在呈现了,在这种情况下我们得到: 警告:
这是我的第一个 iOS 应用程序。 所以我有一个 UIVIewController 和一个 UITableView,其中我按顺序集成了一个 UISearchBar 和一个 UISearchContro
我的模式允许一个特定的元素是可选的,但是当我稍后在文件中遇到一个不同的也是可选的元素时,我需要前一个元素存在。我如何通过 XSD 确保这一点? 例子: true 应该是有效的,
我正在使用 xcode 4.5.2 并为相机按钮创建了自己的 OverlayViewController。 现在,当我的委托(delegate) Controller - TakePhotoViewC
如何在 MVP 中创建 View ? Presenter 是否总是创建它们(除了 subview 的 View 之外)?或者它是一个单独的第三方组件或应用程序或创建它们的东西? 我们还要补充一点,我可
当我调用viewController.presentViewController时,如果已经存在另一个 Controller ,则会出现以下警告。 Warning: Attempt to presen
我有一个关于 React Native 的模块,并在这个问题的标题中抛出错误。这是模块的代码,我不知道 swift 或 Objective-C,所以我需要你像“swift for idiots”一样解
我在 didSelectRowAtIndexPath 中选择一个 segue 时收到上面的警告。这发生在 iPad 上。 iPhone 给出了不同的警告,我会看看是否可以解决这个问题。 我在方法中确实
我的应用程序中有一个包含两个场景的 StoryBoard - 它使用自动转场(在 IB 中创建)。当在第一个 UIViewController 中单击按钮时,第二个 UIViewController
如何在成功验证登录后转到我的第二页? 我已经从登录页面 View Controller (不是登录按钮)拉出一个 segue 到下一页,并将该 segue 命名为“nextPage”。 (如果我从登录
我正在构建一个应用程序,最近发现了由传统转场引起的巨大内存泄漏。因此我了解了 unwind segue。如果我简单地使用,一切都很好: @IBAction func prepareForUnw
我不知道如何将按钮添加到 link_to_add_fields 中 在我制作的 Rails 应用程序中。 我尝试在各处添加 class: "btn btn-mini btn-info",但我一直收到
大家好,感谢阅读。我正在制作一个应用程序,您可以在其中拍照并从相机胶卷中检索照片并将其显示在 View 中。问题是,当我尝试使用调出相机胶卷的按钮时,出现如上标题中的错误“演示正在进行中”。 如果我注
我有一个模型,其中有两个字段在技术上可以为空。字段名称是 :is_activated 和 :activated_at。 :activated_at 仅在 :is_activated 设置为 true
我是一名优秀的程序员,十分优秀!