在 Presenter 中测试协程 class
Testing coroutines in the presenter class
我正在努力测试我的演示者,它正在从存储库层调用一个挂起的函数,如下所示:
override fun viewCreated() {
launch {
val hasPermission = permissionChecker.execute() //suspended function
if (hasPermission) {
foo()
} else {
view.bar()
}
}
主持人也在扩展这个接口:
interface CoroutinePresenter: CoroutineScope {
val job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
fun stopAllActiveJobs() {
coroutineContext.cancelChildren()
}
暂停函数定义如下:
suspend fun execute() : Boolean = withContext(Dispatchers.IO) {
return@withContext class.foo()
}
应用程序中的一切都按预期工作,但是当我尝试编写一些单元测试时,我注意到每当我调用 launch 中的代码时,线程都会切换,但是测试不等待执行。这是测试的实现:
@Test
fun `Test of Suspended Function`() = runBlocking {
presenter.viewCreated()
then(view).should().bar()
...
}
我还添加了建议的库进行测试kotlinx-coroutines-test
,但结果还是一样。我也尝试关注 suggestion and also implementing something like this 但仍然没有成功。
我认为问题是每当在演示者中调用 launch 时实际创建另一个线程,而测试实际上不知道如何等待它。我还尝试 return 一个 Job 并调用 job.join()
但它失败了 NullPointerException
.
希望大家能帮帮我。
我找到了一个解决方案:
按照 this 教程,我已经设置了两个
@Before
fun setup() {
Dispatchers.setMain(Dispatchers.Unconfined)
...
}
@After
fun tearDown() {
Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher
}
并通过 运行 整个 launch 块 presenter
class 在测试中的 runBlocking
语句中。该问题还与挂起函数内的未报告异常有关,该函数实际上不是 mocked 但我看不到它。
现在一切正常。
首先,我强烈建议像这样给你的 coroutineContext 作为参数:
class CoroutinePresenter(coroutineContext: CoroutineContext): CoroutineScope {
init{
_coroutineContext = coroutineContext
}
override val coroutineContext: CoroutineContext
get() = _coroutineContext
// Your Methods
}
在您的真实环境中:
@YourScope
@Provides
fun providesCoroutinePresenter(coroutineContext:CoroutineContext ){
return CoroutinePresenter()
}
@YourScope
@Provides
fun providesCoroutineContext(){
return Dispatchers.Main + job
}
单元测试期间:
@Before
fun setUp() {
coroutinePresenter CoroutinePresenter(Dispatchers.Unconfined)
}
@Test
fun `Should do something`(){
//WHEN
coroutinePresenter.doSomething(params)
//THEN
do your assertions
}
有关更多信息,请查看 SOLID 原则 对于这种情况 D
我正在努力测试我的演示者,它正在从存储库层调用一个挂起的函数,如下所示:
override fun viewCreated() {
launch {
val hasPermission = permissionChecker.execute() //suspended function
if (hasPermission) {
foo()
} else {
view.bar()
}
}
主持人也在扩展这个接口:
interface CoroutinePresenter: CoroutineScope {
val job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
fun stopAllActiveJobs() {
coroutineContext.cancelChildren()
}
暂停函数定义如下:
suspend fun execute() : Boolean = withContext(Dispatchers.IO) {
return@withContext class.foo()
}
应用程序中的一切都按预期工作,但是当我尝试编写一些单元测试时,我注意到每当我调用 launch 中的代码时,线程都会切换,但是测试不等待执行。这是测试的实现:
@Test
fun `Test of Suspended Function`() = runBlocking {
presenter.viewCreated()
then(view).should().bar()
...
}
我还添加了建议的库进行测试kotlinx-coroutines-test
,但结果还是一样。我也尝试关注 job.join()
但它失败了 NullPointerException
.
希望大家能帮帮我。
我找到了一个解决方案: 按照 this 教程,我已经设置了两个
@Before
fun setup() {
Dispatchers.setMain(Dispatchers.Unconfined)
...
}
@After
fun tearDown() {
Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher
}
并通过 运行 整个 launch 块 presenter
class 在测试中的 runBlocking
语句中。该问题还与挂起函数内的未报告异常有关,该函数实际上不是 mocked 但我看不到它。
现在一切正常。
首先,我强烈建议像这样给你的 coroutineContext 作为参数:
class CoroutinePresenter(coroutineContext: CoroutineContext): CoroutineScope { init{ _coroutineContext = coroutineContext } override val coroutineContext: CoroutineContext get() = _coroutineContext // Your Methods }
在您的真实环境中:
@YourScope @Provides fun providesCoroutinePresenter(coroutineContext:CoroutineContext ){ return CoroutinePresenter() } @YourScope @Provides fun providesCoroutineContext(){ return Dispatchers.Main + job }
单元测试期间:
@Before fun setUp() { coroutinePresenter CoroutinePresenter(Dispatchers.Unconfined) } @Test fun `Should do something`(){ //WHEN coroutinePresenter.doSomething(params) //THEN do your assertions }
有关更多信息,请查看 SOLID 原则 对于这种情况 D