The importance of unit testing
Are you writing code in TDD? I guess not.
But we all know unit testing can easily catch issues, and they’re incredibly cheap in terms of resources, especially time.
I’ll show you a case of how.
Please familiarize yourself with the code in snippet 1 (return types for the calls in comments) and the corresponding test in snippet 2.
Snippet 1.
input.id // PublishSubject<String>
.flatMapSingle { api.getSomething(it) } // Single<Value>
.doFinally { isLoading = false }
.subscribe(
{ value ->
render(value)
},
{ errorEvent.trigger() }
)
.addTo(disposable)
Snippet 2.
@Test
fun `Given user has earned something, When screen opened and value loaded, Then loading stopped`() {
// Given
every { api.getSomething(any()) } returns Single.just(something)
// When
viewModel.onViewResumed()
viewModel.input.id.accept("")
// Then
assertThat(viewModel.isLoading).isFalse
}
It turned out that my assertion was not correct. The ViewModel stayed in the loading state somehow, and I didn’t understand the reasons.
I assumed that I’m simply making a network call, which is a Single<T>
, that will signal a Complete event, and the doFinally
block will catch this and stop the loading.
Solution
After a quick look, I understood that I’m not facing a Single
, rather than an Observable
, which will not complete, and loading will never stop.
I fixed the issue, as shown in snippet 3: added stop loading events into more places.
Snippet 3.
input.id // PublishSubject<String>
.flatMapSingle { api.getSomething(it) } // Single<Value>
.doFinally { isLoading = false }
.subscribe(
{ value ->
isLoading = false
render(value)
},
{
isLoading = false
errorEvent.trigger()
}
)
.addTo(disposable)
Conclusion
That’s why unit tests can be helpful and are essential: they can easily confirm your assumptions (I’m just doing an API call) or point to issues in your code (loading is not stopped).
Hint
Finding out the type of a particular call chain, I often use this approach:
- Add it to a separate variable - snippet 4
- Press
Ctrl + Q
on Linux orF1
on Mac to see the type of the variable
Snippet 4.
val asd =
input.id
.flatMapSingle { api.getSomething(it) }