Я столкнулся с очень странной проблемой при написании модульных тестов для Coroutines и потока.insertScene should return Success тест не удался и сказал мне, что поток не получил значение, но я ясно отправил значение, и последующие методы испытаний, такие как deleteScene should return Success , смогли пройти тест.@RunWith(RobolectricTestRunner::class)
@OptIn(ExperimentalCoroutinesApi::class)
class SceneExecuteRepositoryTest {
@MockK
private lateinit var mockConn: EditorServiceConnection
@MockK
private lateinit var mockEditApi: IEditorApi
@MockK
private lateinit var mockSceneDesc: SceneDesc
private val testDispatcher = StandardTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val serviceStateFlow = MutableStateFlow(null)
private val slotActionCallback = slot()
private val sceneExecuteRepository by lazy {
SceneExecuteRepository(mockConn, testScope)
}
@Before
fun setUp() {
MockKAnnotations.init(this)
mockkStatic(XLog::class)
every { XLog.init(any(), any(), any()) } just Runs
every { XLog.tag(any()).d(any()) } just Runs
every { XLog.tag(any()).e(any()) } just Runs
every { mockConn.service } returns serviceStateFlow.filterNotNull()
}
@After
fun tearDown() {
unmockkAll()
}
@Test
fun `insertScene should return Success`() = testScope.runTest {
coEvery {
mockEditApi.insertScene(any(), any(), capture(slotActionCallback))
} answers {
slotActionCallback.captured.onSuccess()
}
serviceStateFlow.value = mockEditApi
val result = sceneExecuteRepository.insertScene(mockSceneDesc, "")
assert(result is SceneActionResult.Success)
coVerify { mockEditApi.insertScene(any(), any(), any()) }
}
@Test
fun `deleteScene should return Success`() = testScope.runTest {
coEvery {
mockEditApi.deleteScene(any(), capture(slotActionCallback))
} answers {
slotActionCallback.captured.onSuccess()
}
serviceStateFlow.value = mockEditApi
val result = sceneExecuteRepository.deleteScene("")
assert(result is SceneActionResult.Success)
coVerify { mockEditApi.deleteScene(any(), any()) }
}
@Test
fun `updateScene should return Success`() = testScope.runTest {
coEvery {
mockEditApi.updateScene(any(), any(), any(), capture(slotActionCallback))
} answers {
slotActionCallback.captured.onSuccess()
}
serviceStateFlow.value = mockEditApi
val result = sceneExecuteRepository.updateScene("", mockSceneDesc, null)
assert(result is SceneActionResult.Success)
coVerify { mockEditApi.updateScene(any(), any(), any(), any()) }
}
}
< /code>
@Singleton
class SceneExecuteRepository @Inject constructor(
private val conn: EditorServiceConnection,
@IoDispatcher private val ioScope: CoroutineScope
) {
companion object {
const val TAG = "SceneExecuteRepository"
}
suspend fun insertScene(
sceneDesc: SceneDesc,
featureId: String? = null
): SceneActionResult {
return executeAction { iEditorApi, callback ->
LogUtil.d(TAG, "insertScene: ${sceneDesc.name}")
iEditorApi.insertScene(sceneDesc, featureId, callback)
}
}
suspend fun deleteScene(sceneId: String): SceneActionResult {
return executeAction { iEditorApi, callback ->
LogUtil.d(TAG, "deleteScene: $sceneId")
iEditorApi.deleteScene(sceneId, callback)
}
}
suspend fun updateScene(
sceneId: String,
sceneDesc: SceneDesc,
featureId: String? = null
): SceneActionResult {
return executeAction { iEditorApi, callback ->
LogUtil.d(TAG, "updateScene: $sceneId")
iEditorApi.updateScene(sceneId, sceneDesc, featureId, callback)
}
}
@OptIn(FlowPreview::class)
private suspend fun executeAction(
action: suspend (IEditorApi, IActionCallback) -> Unit
): SceneActionResult = suspendCancellableCoroutine { coroutine ->
val weakContinuation = WeakReference(coroutine)
val callback = object : IActionCallback.Stub() {
override fun onSuccess() {
weakContinuation.get()?.takeIf { it.isActive }
?.resume(SceneActionResult.Success(Unit))
}
override fun onError(code: Int, desc: String?) {
weakContinuation.get()?.takeIf { it.isActive }
?.resume(SceneActionResult.Error(code, desc ?: ""))
}
}
ioScope.launch {
conn.service
.timeout(3000.milliseconds)
.map {
LogUtil.d(TAG, "$it")
action(it, callback)
}
.catch {
LogUtil.e(TAG, it.toString())
}
.first()
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... s-and-flow
Проблемы с модульными тестированием с коратиками котлин и потоком ⇐ Android
Форум для тех, кто программирует под Android
-
Anonymous
1752138652
Anonymous
Я столкнулся с очень странной проблемой при написании модульных тестов для Coroutines и потока.insertScene should return Success тест не удался и сказал мне, что поток не получил значение, но я ясно отправил значение, и последующие методы испытаний, такие как [b]deleteScene should return Success [/b], смогли пройти тест.@RunWith(RobolectricTestRunner::class)
@OptIn(ExperimentalCoroutinesApi::class)
class SceneExecuteRepositoryTest {
@MockK
private lateinit var mockConn: EditorServiceConnection
@MockK
private lateinit var mockEditApi: IEditorApi
@MockK
private lateinit var mockSceneDesc: SceneDesc
private val testDispatcher = StandardTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val serviceStateFlow = MutableStateFlow(null)
private val slotActionCallback = slot()
private val sceneExecuteRepository by lazy {
SceneExecuteRepository(mockConn, testScope)
}
@Before
fun setUp() {
MockKAnnotations.init(this)
mockkStatic(XLog::class)
every { XLog.init(any(), any(), any()) } just Runs
every { XLog.tag(any()).d(any()) } just Runs
every { XLog.tag(any()).e(any()) } just Runs
every { mockConn.service } returns serviceStateFlow.filterNotNull()
}
@After
fun tearDown() {
unmockkAll()
}
@Test
fun `insertScene should return Success`() = testScope.runTest {
coEvery {
mockEditApi.insertScene(any(), any(), capture(slotActionCallback))
} answers {
slotActionCallback.captured.onSuccess()
}
serviceStateFlow.value = mockEditApi
val result = sceneExecuteRepository.insertScene(mockSceneDesc, "")
assert(result is SceneActionResult.Success)
coVerify { mockEditApi.insertScene(any(), any(), any()) }
}
@Test
fun `deleteScene should return Success`() = testScope.runTest {
coEvery {
mockEditApi.deleteScene(any(), capture(slotActionCallback))
} answers {
slotActionCallback.captured.onSuccess()
}
serviceStateFlow.value = mockEditApi
val result = sceneExecuteRepository.deleteScene("")
assert(result is SceneActionResult.Success)
coVerify { mockEditApi.deleteScene(any(), any()) }
}
@Test
fun `updateScene should return Success`() = testScope.runTest {
coEvery {
mockEditApi.updateScene(any(), any(), any(), capture(slotActionCallback))
} answers {
slotActionCallback.captured.onSuccess()
}
serviceStateFlow.value = mockEditApi
val result = sceneExecuteRepository.updateScene("", mockSceneDesc, null)
assert(result is SceneActionResult.Success)
coVerify { mockEditApi.updateScene(any(), any(), any(), any()) }
}
}
< /code>
@Singleton
class SceneExecuteRepository @Inject constructor(
private val conn: EditorServiceConnection,
@IoDispatcher private val ioScope: CoroutineScope
) {
companion object {
const val TAG = "SceneExecuteRepository"
}
suspend fun insertScene(
sceneDesc: SceneDesc,
featureId: String? = null
): SceneActionResult {
return executeAction { iEditorApi, callback ->
LogUtil.d(TAG, "insertScene: ${sceneDesc.name}")
iEditorApi.insertScene(sceneDesc, featureId, callback)
}
}
suspend fun deleteScene(sceneId: String): SceneActionResult {
return executeAction { iEditorApi, callback ->
LogUtil.d(TAG, "deleteScene: $sceneId")
iEditorApi.deleteScene(sceneId, callback)
}
}
suspend fun updateScene(
sceneId: String,
sceneDesc: SceneDesc,
featureId: String? = null
): SceneActionResult {
return executeAction { iEditorApi, callback ->
LogUtil.d(TAG, "updateScene: $sceneId")
iEditorApi.updateScene(sceneId, sceneDesc, featureId, callback)
}
}
@OptIn(FlowPreview::class)
private suspend fun executeAction(
action: suspend (IEditorApi, IActionCallback) -> Unit
): SceneActionResult = suspendCancellableCoroutine { coroutine ->
val weakContinuation = WeakReference(coroutine)
val callback = object : IActionCallback.Stub() {
override fun onSuccess() {
weakContinuation.get()?.takeIf { it.isActive }
?.resume(SceneActionResult.Success(Unit))
}
override fun onError(code: Int, desc: String?) {
weakContinuation.get()?.takeIf { it.isActive }
?.resume(SceneActionResult.Error(code, desc ?: ""))
}
}
ioScope.launch {
conn.service
.timeout(3000.milliseconds)
.map {
LogUtil.d(TAG, "$it")
action(it, callback)
}
.catch {
LogUtil.e(TAG, it.toString())
}
.first()
}
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79696803/unit-testing-issues-with-kotlin-coroutines-and-flow[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия