预期:测试Dagger使用空构造函数创建了存储库类
问题:使用mockkconstructor
和confirmverified
创建存储库类时使用Dagger依赖注入来创建Mockk验证正在中断。
使用Dagger的Android构造函数模式实现存储库时,需要一个带有@inject
的空构造函数
以便Dagger应用程序组件AppComponent.kt知道创建类。
当confirmverified
被注释掉时,测试通过。在实现confirmverified
时,将调用和跟踪来自先前测试的方法,从而导致验证失败。
在单元测试中,mockkobject
用于模拟SomeRepository.kt对象,因为它是在Kotlin中手动创建的对象。
SomeRepository.kt
object SomeRepository {
someMethod(...){...}
}
@ExtendWith(SomeTestExtension::class)
class SomeParamUnitTest(val testDispatcher: TestCoroutineDispatcher) {
private fun TestLoad() = teedLoadTestCases()
private lateinit var someViewModel: SomeViewModel
@BeforeAll
fun beforeAll() {
mockkObject(SomeRepository)
...
}
@AfterAll
fun afterAll() {
unmockkAll()
}
@ParameterizedTest
@MethodSource("TestLoad")
fun `Feed Load`(test: FeedLoadTest) = testDispatcher.runBlockingTest {
mockComponents(test)
someViewModel = SomeViewModel(...)
assertContentList(...) // Working as expected.
verifyTests(test)
}
private fun mockComponents(test: FeedLoadTest) {
...
coEvery {
SomeRepository.someMethod(test.isRealtime, any())
} returns mockSomeMethod(test.mockFeedList, test.status)
...
}
private fun verifyTests(test: FeedLoadTest) {
coVerify {
SomeRepository.someMethod(test.isRealtime, any())
}
confirmVerified(SomeRepository)
}
}
class App : Application() {
val appComponent = DaggerAppComponent.create()
...
}
@Singleton
@Component
interface AppComponent {
fun someRepository(): SomeRepository
// The repository is injected inside of a fragment, then passed as a parameter into the ViewModel.
fun inject(someFragment: SomeFragment)
}
@Singleton
class SomeRepository @Inject constructor() {
someMethod(...){...}
}
Someparamunittest.kt
@ExtendWith(SomeTestExtension::class)
class SomeParamUnitTest(val testDispatcher: TestCoroutineDispatcher) {
private fun TestLoad() = teedLoadTestCases()
private lateinit var repository: SomeRepository
private lateinit var someViewModel: SomeViewModel
@BeforeAll
fun beforeAll() {
mockkConstructor(SomeRepository::class)
...
}
@AfterAll
fun afterAll() {
unmockkAll()
}
@ParameterizedTest
@MethodSource("TestLoad")
fun `Feed Load`(test: FeedLoadTest) = testDispatcher.runBlockingTest {
repository = SomeRepository()
mockComponents(test)
someViewModel = SomeViewModel(...)
assertContentList(...) // Working as expected.
verifyTests(test)
}
private fun mockComponents(test: FeedLoadTest) {
...
coEvery {
anyConstructed<SomeRepository>().someMethod(test.isRealtime, any())
} returns mockSomeMethod(test.mockFeedList, test.status)
...
}
private fun verifyTests(test: FeedLoadTest) {
coVerify {
anyConstructed<SomeRepository>().someMethod(test.isRealtime, any())
}
confirmVerified(repository)
}
}
对于运行的每个参数化测试,验证的和记录的调用计数都在累积增加。
java.lang.AssertionError:验证确认失败
这似乎是一个改进,因为已验证和记录的测试不再像以前那样累加每个参数化测试轮。而是找不到正确的方法签名。
java.lang.AssertionError:验证确认失败
已验证的呼叫计数:0已记录的呼叫计数:2
对ClearConstructorMockk
和UnmockkConstructor
分别进行了测试,并收到了与尝试的解决方案#2相同的失败消息。
@ExtendWith(SomeTestExtension::class)
class SomeParamUnitTest(val testDispatcher: TestCoroutineDispatcher) {
private fun TestLoad() = teedLoadTestCases()
private val repository = mockkClass(SomeRepository::class)
private lateinit var someViewModel: SomeViewModel
@AfterAll
fun afterAll() {
unmockkAll()
}
@ParameterizedTest
@MethodSource("TestLoad")
fun `Feed Load`(test: FeedLoadTest) = testDispatcher.runBlockingTest {
mockComponents(test)
someViewModel = SomeViewModel(...)
assertContentList(...) // Working as expected.
verifyTests(test)
}
private fun mockComponents(test: FeedLoadTest) {
...
coEvery {
repository.someMethod(test.isRealtime, any())
} returns mockSomeMethod(test.mockFeedList, test.status)
...
}
private fun verifyTests(test: FeedLoadTest) {
coVerify {
repository.someMethod(test.isRealtime, any())
}
confirmVerified(repository)
}
}
我正在使用Dagger 2,在为我的类实现测试时,模块中的generate singleton providers存在一些问题。 所以我有两个问题。 > 我不能使用构造函数注入,因为有一个默认的构造函数。如何从测试模块中获取Foo? 在和中,如何确保在运行每个测试时创建的新实例? 谢谢
这很好,但是如果我使用全局组件甚至子组件中的一个模块,那么应该传入上下文。因此,这意味着如果我用匕首注入演示器,它将被绑定到ApplicationContext。这使得作为JUnit进行测试变得困难。Android代码不应该在演示器中。 所以我想问的是,最好的做法是只在活动、片段、广播接收器和服务中使用匕首吗?就mvp架构而言,这就是。另一个解决方案是设计另一个dagger组件,但不是与appco
我在android项目中使用Dagger2我有两个作用域:ActivityScope和FragmentScope我读了一些示例代码,他们说定义并使用ActivityScope,所以对象将在activity lifecycle中销毁。因为活动和片段有不同的生命周期,所以我们应该有两个作用域。 我的问题是:我是否需要做一些事情让代码知道,当我使用ActivityScope时,对象应该随活动生命周期一起
我正在尝试通过修改MVP应用程序Belajar应用程序在MVVM架构中应用DaggerApplicationComponent,但是我刚刚收到未解决的引用:DaggerApplicationComponent的错误。Kotlin kapt 已被应用,我尝试重建项目,但我从应用程序组件收到错误:C:\Users\3\AndroidStudioProjects\belajar3 - Copy (3)\
Dagger 2即将面世,但可用的示例甚至无法立即编译,文档是Dagger 1的复制粘贴替换。 有没有人有一个在谷歌的Dagger 2上运行的正确应用程序的例子?
我找到了静态编程语言Lazy对象的答案,在这里使用:静态编程语言:检查Lazy val是否已初始化 但看起来像匕首。Lazy没有相同的公共方法。 这就是我如何懒洋洋地使用Dagger注射: 如何在不调用someService的情况下检查someService是否已初始化。get()哪个将初始化它?除了引入布尔标志并自己跟踪它之外。。 谢谢