Кто-нибудь пробовал StateFlow в KMP? Если да, может ли кто-нибудь посоветовать мне написать модульный тест для StateFlow? Я следую архитектуре MVVM и пытаюсь создать общую модель просмотра, которая может использоваться на любой платформе.
В приведенном ниже примере я пытаюсь протестировать LoginViewModel из его метода входа .
LoginViewModel.kt:
@ExperimentalCoroutinesApi
class LoginViewModel(private val loginViewState: LoginViewState, private val loginService: LoginService) {
private val _apiStateFlow = MutableStateFlow(loginViewState)
val stateFlow: StateFlow<LoginViewState> = _apiStateFlow
private val _EMAIL_REGEX = "^[A-Za-z](.*)([@]{1})(.{1,})(\\.)(.{1,})"
suspend fun login(email: String, password: String) {
if (isFormValid(email, password)) {
_apiStateFlow.value = loginViewState.copy(isLoginApiLoading = true)
runCatching {
loginService.login(email, password)
}.onSuccess {
loginViewState.copy(isLoginApiLoading = false, loginResponse = it)
}.onFailure {
loginViewState.copy(isLoginApiLoading = false, errorResponse = ErrorResponse(it.message.orEmpty()))
}
}
}
fun isFormValid(email: String, password: String): Boolean {
val isEmailValid = email.isEmailValid()
val isPasswordValid = password.isPasswordValid()
_apiStateFlow.value = loginViewState.copy(isValidEmail = isEmailValid, isValidPassword = isPasswordValid)
return isEmailValid && isPasswordValid
}
private fun String.isEmailValid() = _EMAIL_REGEX.toRegex().matches(this)
private fun String.isPasswordValid() = length in 6..14
}
data class LoginViewState(
val email: String = "",
val password: String = "",
val isValidEmail: Boolean = false,
val isValidPassword: Boolean = false,
val isLoginApiLoading: Boolean = false,
val loginResponse: LoginResponse? = null,
val errorResponse: ErrorResponse? = null
)
Service.kt:
expect val platformEngine: HttpClientEngineFactory<HttpClientEngineConfig>
val myHttpClient: HttpClient
get() = HttpClient(platformEngine) {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
install(Logging) {
level = LogLevel.ALL
}
expectSuccess = false
HttpResponseValidator {
validateResponse { response: HttpResponse ->
println("Response: $response")
val statusCode = response.status.value
when (statusCode) {
in 300..399 -> throw RedirectResponseException(response)
in 400..499 -> throw ClientRequestException(response)
in 500..599 -> throw ServerResponseException(response)
}
if (statusCode >= 600) {
throw ResponseException(response)
}
}
handleResponseException { cause: Throwable ->
println("Exception: $cause")
}
}
defaultRequest {
url {
host = "127.0.0.1:8080/"
protocol = URLProtocol.HTTP
}
timeout {
connectTimeoutMillis = 10000
requestTimeoutMillis = 10000
socketTimeoutMillis = 10000
}
}
}
LoginService.kt:
class LoginService(private val httpClient: HttpClient) {
suspend fun login(email : String, password : String): LoginResponse = httpClient.post {
body = LoginRequest(email, password)
}
}
LoginReqRes.kt:
data class LoginRequest(val email: String = "", val password: String = "")
data class LoginResponse(val name: String = "", val age: Int = 0, val email: String = "")
data class ErrorResponse(val message: String)