I am trying to perform a unit test and mock a retrofit call using MockWebServer without success. When I run my test, it should run execute() block. When I test my code without CoroutineScope, it works. But I must launch that method in a coroutine scope.
How to successfully mock API call using MockWebServer inside CoroutineScope?
Test class:
private val mockWebServer = MockWebServer()
private val client = OkHttpClient.Builder()
.build()
private val api = Retrofit.Builder()
.baseUrl(mockWebServer.url("/"))
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(SensorsApi::class.java)
@OptIn(DelicateCoroutinesApi::class)
private val mainThreadSurrogate = newSingleThreadContext("UI thread")
// ...
@OptIn(ExperimentalCoroutinesApi::class)
@BeforeAll
fun beforeAll() {
Dispatchers.setMain(mainThreadSurrogate)
}
Test method:
@Test
fun `Loads sensors`() = runTest {
val mDispatcher = object : Dispatcher() {
override fun dispatch(request: RecordedRequest): MockResponse {
val sensorsRegex = Regex("/")
return if (request.path?.matches(sensorsRegex) == true) {
MockResponse().setBody("[1]")
} else {
MockResponse().setResponseCode(500)
}
}
}
mockWebServer.dispatcher = mDispatcher
//mockWebServer.enqueue(MockResponse().setBody("[1, 2, 3]"))
viewModel.loadSensors()
}
Method I test in ViewModel:
fun loadSensors() {
CoroutineScope(Dispatchers.IO).launch {
sensorsService.getUserSensors("", "")
.execute().let {
println("inside getUserSensors()") // not executed
if (it.isSuccessful) {
loadingDialog.postValue(Event(false))
consumeLoadedSensors(it)
} else {
loadingDialog.postValue(Event(false))
showLoadSensorsFailure()
}
}
}
}