Ответ для SearchWeatherUseCase не найден (# 1 среди настроенных ответов: () io.mockk.MockKException: ответ не найден дляAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Ответ для SearchWeatherUseCase не найден (# 1 среди настроенных ответов: () io.mockk.MockKException: ответ не найден для

Сообщение Anonymous »

Я пытаюсь реализовать модульное тестирование для своего приложения. У меня есть ViewModel, которая принимает варианты использования в качестве параметров, введенных в конструктор ниже
@HiltViewModel
class WeatherViewModel @Inject constructor(
private val searchWeatherUseCase: SearchWeatherUseCase,
) : ViewModel() {

private val _uiState: MutableStateFlow =
MutableStateFlow(WeatherUiState(isLoading = true))
val uiState: StateFlow = _uiState.asStateFlow()

private val _searchWidgetState: MutableState =
mutableStateOf(value = SearchWidgetState.CLOSED)
val searchWidgetState: State = _searchWidgetState

private val _searchTextState: MutableState = mutableStateOf(value = "")
val searchTextState: State = _searchTextState

fun updateSearchWidgetState(newValue: SearchWidgetState) {
_searchWidgetState.value = newValue
}

fun updateSearchTextState(newValue: String) {
_searchTextState.value = newValue
}

init {
getWeather()
}

fun getWeather(city: String = DEFAULT_WEATHER_DESTINATION) {
searchWeatherUseCase.getCities(city).map { result ->
when (result) {
is Result.Success -> {
val apiData = result.data
val isFavorite = data.find { apiData.name == it.name }
_uiState.value = WeatherUiState(
weather = apiData,

)
}

is Result.Error -> {
_uiState.value = WeatherUiState(errorMessage = result.errorMessage)
}

Result.Loading -> {
_uiState.value = WeatherUiState(isLoading = true)
}
}
}.launchIn(viewModelScope)

}

Затем запрос передается в UseCase, а затем
class SearchWeatherUseCase @Inject constructor(private val repositoryImpl: WeatherRepositoryImpl) {
fun getCities(cityName: String): Flow {
return repositoryImpl.findCityWeather(cityName)
}
}

который затем передает запрос классу реализации:
class WeatherRepositoryImpl @Inject constructor(
private val remoteSource: RemoteSource,
private val localSource: LocalSource,
private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
) : WeatherRepository {

override fun findCityWeather(city: String): Flow = flow {
emit(Result.Loading)
try {
val result = remoteSource.findCityWeatherData(city)
emit(Result.Success(result))
} catch (exception: HttpException) {
emit(Result.Error(exception.message.orEmpty()))
} catch (exception: IOException) {
emit(Result.Error("Please check your network connection and try again!"))
}
}.flowOn(dispatcher)

override suspend fun saveFavCity(favouriteCity: Weather) = localSource.saveCity(favouriteCity)

override suspend fun getFavCities(): List {
return localSource.getSaveCities()
}

override suspend fun deleteFavCity(city: String) = localSource.deleteFavCity(city)

override suspend fun fetchFavouriteWeatherByName(name: String): Weather =
localSource.fetchFavouriteWeatherByName(name)

}

который решает, должны ли данные поступать из удаленных или локальных источников. В моем случае это удаленный источник, а именно:
class RemoteSource @Inject constructor(private val api: ApiInterface) {

suspend fun findCityWeatherData(city: String): Weather {
return api.findCityWeatherData(q = city).toWeather()
}
}

Это процесс передачи/испускания данных. А ниже мой WeatherViewModelTest:
@ExperimentalCoroutinesApi
class WeatherViewModelTest {

// Rule to handle LiveData synchronization
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()

// Use MockK to mock use cases
private lateinit var searchWeatherUseCase: SearchWeatherUseCase
private lateinit var saveCityUseCase: SaveCityUseCase
private lateinit var getSaveCityUseCase: GetSaveCityUseCase
private lateinit var deleteSaveCityUseCase: DeleteSaveCityUseCase
private lateinit var getFavouriteCityUseCase: GetFavouriteCityUseCase

// ViewModel under test
private lateinit var weatherViewModel: WeatherViewModel

// Test Dispatcher
private val testDispatcher = StandardTestDispatcher()

@Before
fun setup() {
// Mock the use cases
searchWeatherUseCase = mockk()
getSaveCityUseCase = mockk()
saveCityUseCase = mockk()
deleteSaveCityUseCase = mockk()

// Initialize ViewModel with the mocked use cases
weatherViewModel = WeatherViewModel(
searchWeatherUseCase,
saveCityUseCase,
getSaveCityUseCase,
deleteSaveCityUseCase
)

// Set up common behavior for saving cities
coEvery { getSaveCityUseCase.getSaveCities() } returns listOf(
Weather(
id = 1L,
temperature = 25,
date = "2023-09-25",
wind = 10,
humidity = 60,
feelsLike = 24,
uv = 5,
name = "Cottbus",
isFavourite = true
)
)
}

@Test
fun `getWeather() should update uiState with weather data when result is success`() = runTest {
// Given a successful weather fetch result
val weather = Weather(
id = 1L,
temperature = 25,
date = "2023-09-25",
wind = 10,
humidity = 60,
feelsLike = 24,
uv = 5,
name = "Cottbus",
isFavourite = true
)

// Mock the behavior of searchWeatherUseCase.getCities for "Cottbus"
coEvery { searchWeatherUseCase.getCities("Cottbus") } returns flowOf(Result.Success(weather))

// When fetching weather for a city
weatherViewModel.getWeather("Cottbus")

// Run the pending coroutines
advanceUntilIdle()

// Verify that the getCities method was called with "Cottbus"
coVerify { searchWeatherUseCase.getCities("Cottbus") }

// Assert that the ViewModel updates the UI state correctly
val expectedUiState = WeatherUiState(
weather = weather,
favouriteCity = listOf(weather),
isFavorite = true
)

assertEquals(expectedUiState, weatherViewModel.uiState.value)
}

@After
fun tearDown() {
Dispatchers.resetMain() // Reset the dispatcher after the test
}

@Test
fun `getWeather() should update uiState with error when result is failure`() = runTest {
// Given a failure weather fetch result
val errorMessage = "Network error"
coEvery { searchWeatherUseCase.getCities(any()) } returns flowOf(Result.Error(errorMessage))

// When fetching weather for a city
weatherViewModel.getWeather("Test City")

// Run the pending coroutines
advanceUntilIdle()

// Then assert that the UI state is updated with an error message
assertEquals(errorMessage, weatherViewModel.uiState.value.errorMessage)
}
}

Тест не пройден и выдает следующую ошибку:
no answer found for SearchWeatherUseCase(#1).getCities(Cottbus) among the configured answers: ()
io.mockk.MockKException: no answer found for SearchWeatherUseCase(#1).getCities(Cottbus) among the configured answers: ( ) < b r / > a t a p p / / i o . m o c k k . i m p l . s t u b . M o c k K S t u b . d e f a u l t A n s w e r ( M o c k K S t u b . k t : 9 1 ) < b r / > a t a p p / / i o . m o c k k . i m p l . s t u b . M o c k K S t u b . a n s w e r ( M o c k K S t u b . k t : 4 2 ) < b r / > a t a p p / / i o . m o c k k . i m p l . r e c o r d i n g . s t a t e s . A n s w e r i n g S t a t e . c a l l ( A n s w e r i n g S t a t e . k t : 1 6 ) < b r / > a t a p p / / i o . m o c k k . i m p l . r e c o r d i n g . C o m m o n C a l l R e c o r d e r . c a l l ( C o m m o n C a l l R e c o r d e r . k t : 5 3 ) < b r / > a t a p p / / i o . m o c k k . i m p l . s t u b . M o c k K S t u b . h a n d l e I n v o c a t i o n ( M o c k K S t u b . k t : 2 6 9 ) < b r / > a t a p p / / i o . m o c k k . i m p l . i n s t a n t i a t i o n . J v m M o c k F a c t o r y H e l p e r $ m o c k H a n d l e r $ 1 . i n v o c a t i o n ( J v m M o c k F a c t o r y H e l p e r . k t : 2 4 ) < b r / > a t a p p / / i o . m o c k k . p r o x y . j v m . a d v i c e . I n t e r c e p t o r . c a l l ( I n t e r c e p t o r . k t : 2 1 ) < b r / > a t a p p / / c o m . e x a m p l e . w e a t h e r v i e w e r . d a t a . u s e c a s e . S e a r c h W e a t h e r U s e C a s e . g e t C i t i e s ( S e a r c h W e a t h e r U s e C a s e . k t : 1 1 ) < b r / > a t a p p / / c o m . e x a m p l e . w e a t h e r v i e w e r . u i . v i e w m o d e l s . W e a t h e r V i e w M o d e l . g e t W e a t h e r ( W e a t h e r V i e w M o d e l . k t : 6 5 ) < b r / > a t a p p / / c o m . e x a m p l e . w e a t h e r v i e w e r . u i . v i e w m o d e l s . W e a t h erViewModel.getWeather$default(WeatherViewModel.kt:64)
at app//com.example.weatherviewer.ui.viewmodels.WeatherViewModel.(WeatherViewModel.kt:60)
at app//WeatherViewModelTest.setup(WeatherViewModelTest.kt:56)
at java.base@17.0.11/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.11/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base@17.0.11/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base@17.0.11/java.lang.reflect.Method.invoke(Method.java:568)
at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at app//org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
at app//org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at app//org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at app//org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
at java.base@17.0.11/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.11/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base@17.0.11/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base@17.0.11/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

no answer found for SearchWeatherUseCase(#5).getCities(Cottbus) among the configured answers: ()
io.mockk.MockKException: no answer found for SearchWeatherUseCase(#5).getCities(Cottbus) among the configured answers: ( ) < b r / > a t a p p / / i o . m o c k k . i m p l . s t u b . M o c k K S t u b . d e f a u l t A n s w e r ( M o c k K S t u b . k t : 9 1 ) < b r / > a t a p p / / i o . m o c k k . i m p l . s t u b . M o c k K S t u b . a n s w e r ( M o c k K S t u b . k t : 4 2 ) < b r / > a t a p p / / i o . m o c k k . i m p l . r e c o r d i n g . s t a t e s . A n s w e r i n g S t a t e . c a l l ( A n s w e r i n g S t a t e . k t : 1 6 ) < b r / > a t a p p / / i o . m o c k k . i m p l . r e c o r d i n g . C o m m o n C a l l R e c o r d e r . c a l l ( C o m m o n C a l l R e c o r d e r . k t : 5 3 ) < b r / > a t a p p / / i o . m o c k k . i m p l . s t u b . M o c k K S t u b . h a n d l e I n v o c a t i o n ( M o c k K S t u b . k t : 2 6 9 ) < b r / > a t a p p / / i o . m o c k k . i m p l . i n s t a n t i a t i o n . J v m M o c k F a c t o r y H e l p e r $ m o c k H a n d l e r $ 1 . i n v o c a t i o n ( J v m M o c k F a c t o r y H e l p e r . k t : 2 4 ) < b r / > a t a p p / / i o . m o c k k . p r o x y . j v m . a d v i c e . I n t e r c e p t o r . c a l l ( I n t e r c e p t o r . k t : 2 1 ) < b r / > a t a p p / / c o m . e x a m p l e . w e a t h e r v i e w e r . d a t a . u s e c a s e . S e a r c h W e a t h e r U s e C a s e . g e t C i t i e s ( S e a r c h W e a t h e r U s e C a s e . k t : 1 1 ) < b r / > a t a p p / / c o m . e x a m p l e . w e a t h e r v i e w e r . u i . v i e w m o d e l s . W e a t h e r V i e w M o d e l . g e t W e a t h e r ( W e a t h e r V i e w M o d e l .kt:65)
at app//com.example.weatherviewer.ui.viewmodels.WeatherViewModel.getWeather$default(WeatherViewModel.kt:64)
at app//com.example.weatherviewer.ui.viewmodels.WeatherViewModel.(WeatherViewModel.kt:60)
at app//WeatherViewModelTest.setup(WeatherViewModelTest.kt:56)
at java.base@17.0.11/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.11/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base@17.0.11/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base@17.0.11/java.lang.reflect.Method.invoke(Method.java:568)
at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at app//org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
at app//org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at app//org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at app//org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
at java.base@17.0.11/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.11/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base@17.0.11/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base@17.0.11/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)


Подробнее здесь: https://stackoverflow.com/questions/790 ... swers-io-m
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»