- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
android studio 3.4.1
dagger-android 2.21
我正在使用 dagger-android 将我的 OKHttpClient 注入(inject)到 espresso 规则中。但是还没有找到一种方法来做到这一点,我尝试了很多不同的事情。
这是我正在使用的规则,我正在尝试将 okHttpClient 注入(inject)其中
class OkHttpIdingResourceRule(application: Application) : TestRule {
/* My attempt below - but not working */
private val testApplication =
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
as AndroidTestGoWeatherApplication
// private val testApplication = application.applicationContext as AndroidTestGoWeatherApplication
private val component = testApplication.component as AndroidTestGoWeatherPresentationComponent
private val okHttpClient: OkHttpClient = component.okHttpClient()
private val idlingResource: IdlingResource = OkHttp3IdlingResource.create("okhttp", okHttpClient)
override fun apply(base: Statement?, description: Description?): Statement {
return object: Statement() {
override fun evaluate() {
IdlingRegistry.getInstance().register(idlingResource)
base?.evaluate()
IdlingRegistry.getInstance().unregister(idlingResource)
}
}
}
}
这是我的 AndroidTestGoWeatherApplication
class AndroidTestGoWeatherApplication : GoWeatherApplication(), HasActivityInjector {
@Inject
lateinit var activityInjector: DispatchingAndroidInjector<Activity>
override fun activityInjector(): AndroidInjector<Activity> = activityInjector
}
我的申请
open class GoWeatherApplication : Application(), HasActivityInjector, HasSupportFragmentInjector, HasServiceInjector {
@Inject
lateinit var dispatchingAndroidActivityInjector: DispatchingAndroidInjector<Activity>
@Inject
lateinit var dispatchingAndroidFragmentInjector: DispatchingAndroidInjector<Fragment>
@Inject
lateinit var dispatchingAndroidServiceInjector: DispatchingAndroidInjector<Service>
lateinit var component: GoWeatherComponent
override fun onCreate() {
super.onCreate()
component = DaggerGoWeatherComponent
.builder()
.application(this)
.build()
component.inject(this)
}
override fun activityInjector(): AndroidInjector<Activity> {
return dispatchingAndroidActivityInjector
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
return dispatchingAndroidFragmentInjector
}
override fun serviceInjector(): AndroidInjector<Service> {
return dispatchingAndroidServiceInjector
}
}
我的主要应用组件
GoWeatherComponent
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
ActivityBuilder::class,
NetworkModule::class,
GoWeatherApplicationModule::class])
interface GoWeatherComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: GoWeatherApplication): Builder
fun build(): GoWeatherComponent
}
fun inject(application: GoWeatherApplication)
}
我的测试应用程序组件
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
TestNetworkModule::class,
TestGoWeatherApplicationModule::class,
TestForecastModule::class])
interface AndroidTestGoWeatherPresentationComponent : AndroidInjector<AndroidTestGoWeatherApplication> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<AndroidTestGoWeatherApplication>() {
abstract fun applicationModule(TestApplicationModule: TestGoWeatherApplicationModule): Builder
abstract fun testNetworkModule(testNetworkModule: TestNetworkModule): Builder
}
fun okHttpClient(): OkHttpClient
}
这是我创建 OkHttpClient 的 TestNetworkModule
@Module
class TestNetworkModule {
@Singleton
@Provides
fun httpLoggingInterceptor(): HttpLoggingInterceptor {
val loggingInterceptor = HttpLoggingInterceptor()
loggingInterceptor.level = if(BuildConfig.DEBUG) {
HttpLoggingInterceptor.Level.BODY
}
else {
HttpLoggingInterceptor.Level.NONE
}
return loggingInterceptor
}
@Singleton
@Provides
fun provideOkHttpClient(httpLoggingInterceptor: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.connectTimeout(2, TimeUnit.SECONDS)
.readTimeout(2, TimeUnit.SECONDS)
.build()
}
@Named("TestBaseUrl")
@Singleton
@Provides
fun provideBaseUrlTest(): String =
"http://localhost:8080/"
@Singleton
@Provides
fun provideRetrofit(@Named("TestBaseUrl") baseUrl: String, okHttpClient: OkHttpClient?): Retrofit {
return Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient!!)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
}
}
我的 Activity 生成器
@Module
abstract class ActivityBuilder {
@ContributesAndroidInjector(modules = [ActivityModule::class])
abstract fun injectIntoHomeActivity(): ForecastActivity
@ContributesAndroidInjector(modules = [ActivityModule::class, ForecastModule::class])
abstract fun injectIntoForecastFragment(): ForecastFragment
}
我的主要 Activity
class ForecastActivity : AppCompatActivity(), ForecastView, RetryListener, LocationUtilsListener {
companion object {
const val WEATHER_FORECAST_KEY = "weatherForecast"
}
@Inject
lateinit var forecastPresenter: ForecastPresenter
@Inject
lateinit var location: LocationUtils
private var fragmentManager: FragmentManager? = null
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
}
}
我的仪器测试
@RunWith(AndroidJUnit4::class)
class ForecastActivityAndroidTest {
@Inject
lateinit var okHttpClient: OkHttpClient
@get:Rule
val okHttpIdingResourceRule = OkHttpIdingResourceRule(InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as AndroidTestGoWeatherApplication)
@get:Rule
val activityRule = ActivityTestRule(ForecastActivity::class.java, false, false)
private val mockWebserver: MockWebServer by lazy {
MockWebServer()
}
@Before
fun setUp() {
val testApplication =
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
as AndroidTestGoWeatherApplication
DaggerAndroidTestGoWeatherPresentationComponent
.builder()
.applicationModule(TestGoWeatherApplicationModule())
.create(testApplication)
.inject(testApplication)
mockWebserver.start(8080)
}
@After
fun tearDown() {
mockWebserver.shutdown()
}
@Test
fun should_load_five_day_forecast() {
loadFromResources("json/fivedayforecast.json")
mockWebserver.enqueue(MockResponse().setBody(loadFromResources("json/fivedayforecast.json")))
ActivityScenario.launch(ForecastActivity::class.java)
/* do some testing here *
}
}
提前致谢
最佳答案
我认为您正在以错误的方式将 OkHttpClient
依赖项注入(inject)到 OkHttpIdingResourceRule
中。
来自 Dagger 2 文档:
Constructor injection is preferred whenever possible...
你拥有 OkHttpIdingResourceRule
所以你真的应该在这里进行构造函数注入(inject)。
通过将构造函数更改为如下所示,允许 Dagger 为您构造 OkHttpIdingResourceRule
:
class OkHttpIdingResourceRule @Inject constructor(application: Application, okHttpClient: OkHttpClient)
由于 OkHttpClient
已经在您的对象图中,我会将 OkHttpIdingResourceRule
注入(inject)您的测试 而不是 OkHttpClient
综上所述,我认为您的代码的其他部分仍然存在一些问题,但如果不运行它并亲自查看错误,我无法确认它们。例如,如果您计划以这种方式注入(inject)此测试,那么您必须在测试组件上使用这样的方法:
void inject(ForecastActivityAndroidTest 测试);
编辑:
我再次查看了您的规则,看起来您真正感兴趣的是注入(inject) IdlingResource
。如果是这种情况,您应该将构造函数更改为如下所示:
class OkHttpIdingResourceRule @Inject constructor(idlingRes: IdlingResource)
从那里您可以做的是在您的 TestNetworkModule
中创建一个为您创建它的配置方法:
@Provides
IdlingResource providesIdlingResource(OkHttpClient okHttpClient {
return OkHttp3IdlingResource.create("okhttp", okHttpClient)
}
关于android - 为仪器测试注入(inject) espresso 规则的依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56704449/
在android支持测试库中,为recyclerview编写测试用例时,某些演示使用TypeSafeMatcher,而其他演示则使用BoundedMatcher。谁能解释我为什么在使用示例或用例时使用
我们目前正在为我们的应用程序的一个区域编写 Espresso UI 测试,这需要我们在每次测试后清除应用程序数据 我们之前尝试过使用 Android Orchestrator 我们之前曾尝试使用带有
我已经看到了一些关于它的问题。 例如。 Android Espresso testing app flow 但是上面的答案在espresso 2中不起作用。这是我的摘录 @Rule public Ac
我正在尝试建立一个测试农场,但我发现了一个很大的障碍。手机处于休眠状态时无法运行 Espresso 测试。 android.support.test.espresso.NoActivityResume
我正在运行“gradlew connectedCheck”来在已安装的应用程序上运行 Espresso 测试,但是这个“gradlew connectedCheck”重写了我的应用程序,然后运行测试。
使用 AndroidInjector 和 Subcomponents 无法将作用域对象的事件注入(inject) Espresso 的 Test 类。 以前使用应用程序级组件和事件组件,只要您创建一个
我正在使用Espresso为我的Android应用程序编写UI测试,并想使用MockWebServer模拟HTTP请求。 在运行测试之前,我需要模拟身份验证响应并登录用户。 有没有一种方法可以使应用程
我有一个 ExpandableListView,我想 click() 它的一个 subview 。 我尝试了LOADS OF不同的方法,但我似乎无法理解 Espresso 的工作原理。 例如,为什么这
我目前不熟悉自动化测试和使用 Android Studio 使用 Espresso 执行自动化测试,我正在尝试对登录屏幕执行自动化测试,我目前在执行特定按钮的点击时遇到问题。我尝试了多种按钮方法,但对
Windows 10(64 位), 安卓工作室 3.1.2, Gradle 4.4,Java 1.8。 这是我的布局 xml 这里 @drawable/sign_in_login_bg
Firebase 测试实验室接受 App Bundle/APK 和 android 测试 APK,并且动态功能模块 UI 测试在 Firebase 测试实验室中失败。该错误是关于一些多 dex 问题,
根据我在网络上所做的搜索,我发现很少有人认为 Espresso UI 测试框架不支持 WebViews?是这样吗? 最佳答案 Espresso 支持 WebView,我在下面添加了一个示例 http:
使用 Espresso,我希望能够单击 ExpandableListView(名为 CustomExpandableView)的特定子项。 listview 创建一组RelativeLayouts(名
我有我的 xml 布局: 我想写 Espresso 测试检查 EditText 有android:drawableStart="@drawable/ic_sign_in_password". 我该怎
我正在尝试为 Android 应用程序编写 Espresso 测试,并且需要知道如何自动化使用 AutoCompleteTextView 的部分。下面提到了我的应用程序使用的代码: activity_
我正在尝试为 Android 应用程序编写 Espresso 测试,并且需要知道如何自动化使用 AutoCompleteTextView 的部分。下面提到了我的应用程序使用的代码: activity_
在我的应用中,我使用 Kotlin Flow。在我通过 EspressoIdlingResource.increment() 使用挂起函数之前,它不适用于 Kotlin Flow。如何解决这个问题?
在我的应用中,我使用 Kotlin Flow。在我通过 EspressoIdlingResource.increment() 使用挂起函数之前,它不适用于 Kotlin Flow。如何解决这个问题?
我正在尝试使用 onData 运行 espresso 测试,对于其中只有一个 AdapterView 的 View ,一切正常。但是,当屏幕显示其中嵌套了多个适配器 View 的 View 时,我得到
我想测试是否显示 ID 为 imageViewTour 且标签包含 some_text 的 imageView。 我的测试: onView(allOf(withId(R.id.imageViewTou
我是一名优秀的程序员,十分优秀!