当将CoroutineScope注入到用于单元测试的ViewModel中时,是否也应该使用flowon
注入和定义CoroutineDispatcher,即使在生产代码中不需要它?
在此用例中,生产代码中不需要flowon
,因为在someRepository.kt中,reverfit处理dispatchers.io
上的线程,而viewmodelscope
返回dispathers.main
上的数据,这两种情况都是默认的。
对保存在Kotlin流值中的Android的ViewModel视图状态值运行单元测试。
主调度程序的模块初始化失败。对于测试,Dispatcher。可以使用kotlinx-coroutines-test模块中的SetMain
在硬编码CoroutineScope的情况下,单元测试在第一次出现时失败。使用viewmodelscope
以便启动的coroutine将维护viewmodel的生命周期。但是,viewmodelscope
是从ViewModel内部创建的,与可以在ViewModel外部定义并作为参数传入的CoroutineDispatcher相比,这使得注入更加复杂。
SomeViewModel.kt
fun bindIntents(view: FeedView) {
view.initStateIntent().onEach {
initState(view)
}.launchIn(viewModelScope)
}
Sometest.kt
@ExperimentalCoroutinesApi
class SomeTest : BeforeAllCallback, AfterAllCallback {
private val testDispatcher = TestCoroutineDispatcher()
private val testScope = TestCoroutineScope(testDispatcher)
private val repository = mockkClass(FeedRepository::class)
private var loadNetworkIntent = MutableStateFlow<LoadNetworkIntent?>(null)
override fun beforeAll(context: ExtensionContext?) {
// Set Coroutine Dispatcher.
Dispatchers.setMain(testDispatcher)
}
override fun afterAll(context: ExtensionContext?) {
Dispatchers.resetMain()
// Reset Coroutine Dispatcher and Scope.
testDispatcher.cleanupTestCoroutines()
testScope.cleanupTestCoroutines()
}
@Test
fun topCafesPoc() = testDispatcher.runBlockingTest {
coEvery {
repository.getInitialCafes(any())
} returns mockGetInitialCafes(mockCafesList, SUCCESS)
val viewModel = FeedViewModel(repository)
viewModel.bindIntents(object : FeedView {
@ExperimentalCoroutinesApi
override fun initStateIntent() = MutableStateFlow(true)
@ExperimentalCoroutinesApi
override fun loadNetworkIntent() = loadNetworkIntent.filterNotNull()
override fun render(viewState: FeedViewState) {
// TODO: Test viewState
}
})
loadNetworkIntent.value = LoadNetworkIntent(true)
// TODO
// assertEquals(4, 2 + 2)
}
}
注意:在最终版本中将使用JUnit5测试扩展。
在生产中,由于使用了ViewModel的ViewModelScope
,因此使用空的CoroutineScopeProvider
创建ViewModel。对于测试,TestCoroutIneScope
作为ViewModel参数传递。
Someutils.KT
/**
* Configure CoroutineScope injection for production and testing.
*
* @receiver ViewModel provides viewModelScope for production
* @param coroutineScope null for production, injects TestCoroutineScope for unit tests
* @return CoroutineScope to launch coroutines on
*/
fun ViewModel.getViewModelScope(coroutineScope: CoroutineScope?) =
if (coroutineScope == null) this.viewModelScope
else coroutineScope
SomeViewModel.kt
class FeedViewModel(
private val coroutineScopeProvider: CoroutineScope? = null,
private val repository: FeedRepository
) : ViewModel() {
private val coroutineScope = getViewModelScope(coroutineScopeProvider)
fun getSomeData() {
repository.getSomeDataRequest().onEach {
// Some code here.
}.launchIn(coroutineScope)
}
}
@ExperimentalCoroutinesApi
class FeedTest : BeforeAllCallback, AfterAllCallback {
private val testDispatcher = TestCoroutineDispatcher()
private val testScope = TestCoroutineScope(testDispatcher)
private val repository = mockkClass(FeedRepository::class)
private var loadNetworkIntent = MutableStateFlow<LoadNetworkIntent?>(null)
override fun beforeAll(context: ExtensionContext?) {
// Set Coroutine Dispatcher.
Dispatchers.setMain(testDispatcher)
}
override fun afterAll(context: ExtensionContext?) {
Dispatchers.resetMain()
// Reset Coroutine Dispatcher and Scope.
testDispatcher.cleanupTestCoroutines()
testScope.cleanupTestCoroutines()
}
@Test
fun topCafesPoc() = testDispatcher.runBlockingTest {
...
val viewModel = FeedViewModel(testScope, repository)
viewmodel.getSomeData()
...
}
}
问题内容: 这是我的java类: 这是单元测试: 测试失败,因为没有任何人注入。我应该如何正确处理这种情况?是否存在最佳实践? 问题答案: 如果没有像Spring这样的容器(或诸如基于Spring的Unitils之类的容器),则必须手动注入实体管理器。在这种情况下,您 可以 将以下内容用作基类:
问题内容: 我想对用Apache CXF编写的RESTful接口进行单元测试。 我使用ServletContext来加载一些资源,所以我有: 如果我将其部署在Glassfish上,则会注入ServletContext,并且它会按预期工作。但是我不知道如何将ServletContext注入我的服务类中,以便可以使用JUnit测试对其进行测试。 我使用Spring 3.0,JUnit 4,CXF 2.
我有以下用例: 问题2:为什么如果我只使用构造函数而不使用@Autowired或者反之亦然,那么一切都能正常工作,因为我没有加载Spring上下文...我有单元测试...
我的实现出了什么问题?谢谢
引发异常 java.lang.RuntimeException:Android.text.SpannableStringInternal中的方法长度未被模拟。有关详细信息,请参见http://g.co/androidstudio/not-mocked。 这在上面的链接中解释为 我想学习,所以我准备在问答式下面加上我的答案。
问题内容: 我刚开始使用Node,现在正在编写一些单元测试。对于前几个函数,我可以正常运行,但是现在我碰到了一个包含其中的函数。我的函数的简化版本如下所示: 我尝试使用基本节点断言测试库进行测试: 由于执行此操作的时间(以及结果)总是不同的,因此它将始终失败。 在Python中,我可以设置模拟类和对象。有没有一种方法可以在Node中解决此问题而无需将moment.utc()作为函数的参数? 问题答