Florian Walther (live streaming)
01/01/2022, 12:03 PMgetOrAwaitValue
helper function from the Google samples. But this LiveData is coming from a MutableStateFlow
using asLiveData
. There seems to be a race condition and I am not getting a value in my test. I've tried passing the StandardTestDispatcher
to asLiveData
but it didn't change anything.nikolaymetchev
02/14/2022, 1:32 PMChristoph Beylage
03/22/2022, 4:56 PMdata class AppConfig(
var smtp = SmtpConfig(
enabled = false
host = "test",
port = 12345,
useStartTLS = true,
fromName = "test",
from = "<mailto:test@test.de|test@test.de>"
user = ""
password = ""
)
)
val classInstance = AppConfig()
what I want to do in one of our tests is to mock the value of smtp.
What I did - here for example with mockito - was the following:
val spy = Mockito.spy(classInstance)
Mockito.`when`(spy.smtp).thenReturn(SmtpConfig(true)). //true is the enabled flag in this case, so the rest should be null
What Mockito and Mockk are doing in this case is to mock the get method behind that property. This can be verified by starting the debugger right in the line after the Mockito.\`when\` expression.
The field is exactly like initialized above and when I click the getter in the debugger I get the result from spy.smtp, as you can see in the screenshot.
I can understand why this happens, but kotlin simply does not use the getters of those properties why the tests wont work.
So long text, simple question: Any idea how to fix this? Everything I found was a github issue from mockk with exactly the same problem and that has been closed because to support this a major rebuild would be necessary.mbonnin
03/25/2022, 12:31 PMRak
04/01/2022, 9:48 AMobject
class. Is there a way to “reset” the instance? It keeps its state between tests.muthuraj
04/19/2022, 11:59 AMrunTest
alternate from runBlocking
and I'm facing an issue in testing a specific use case. Here is a simplified version of the test case I want to run.
@Test(expected = NullPointerException::class)
fun test() = runTest {
//In my actual code, I'm testing a ViewModel which uses viewModelScope to launch a coroutine
//and it will throw an exception for a specific case.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
scope.launch {
throw NullPointerException("error")
}
}
marzelwidmer
05/09/2022, 8:15 AMSonar
coverage. and value
classes.. and init
function. it looks like the coverage ist not right on sonar. we use the jacoco
maven plugin version 0.8.7
v79
06/10/2022, 6:30 AMspek
and mocck
for testing. I'm getting a gradle error and wondered if someone could help me understand what it means?
Execution failed for task ':compileTestKotlin'.
> Could not resolve all files for configuration ':testCompileClasspath'.
> Could not resolve org.jetbrains.kotlin:kotlin-test-junit5:1.6.21.
Required by:
project :
> Module 'org.jetbrains.kotlin:kotlin-test-junit5' has been rejected:
Cannot select module with conflict on capability 'org.jetbrains.kotlin:kotlin-test-framework-impl:1.6.21' also provided by [org.jetbrains.kotlin:kotlin-test-junit:1.6.21(junitApi)]
> Could not resolve org.jetbrains.kotlin:kotlin-test-junit:1.6.21.
Required by:
project : > io.insert-koin:koin-test:3.2.0 > io.insert-koin:koin-test-jvm:3.2.0
> Module 'org.jetbrains.kotlin:kotlin-test-junit' has been rejected:
Cannot select module with conflict on capability 'org.jetbrains.kotlin:kotlin-test-framework-impl:1.6.21' also provided by [org.jetbrains.kotlin:kotlin-test-junit5:1.6.21(junit5Api)]
From my build.gradle.kts file, I have the following test configuration:
dependencies {
// ...
// testing
testImplementation("io.insert-koin:koin-test:$koin_version")
// testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:$kotlin_version")
testImplementation("org.spekframework.spek2:spek-dsl-jvm:$spek_version")
testRuntimeOnly("org.spekframework.spek2:spek-runner-junit5:$spek_version")
testImplementation("io.mockk:mockk:$mockk_version")
}
tasks.test {
useJUnitPlatform {
includeEngines("spek2")
}
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "11"
}
Just trying to make sense of the error really.zak.taccardi
06/16/2022, 9:07 PMkover
support src/androidTest
?tylerwilson
06/17/2022, 1:56 PMMatthias Geisler
06/21/2022, 8:24 PMMatthias Geisler
06/21/2022, 8:24 PMPiotr Krzemiński
07/05/2022, 9:31 AMigor.wojda
07/19/2022, 9:51 AMadvanceUntilIdle()
method. I wonder where this method belongs in BDD ( When
or Then
block?)
@Test
fun `test something`() = runTest {
// given
setup code
// when
subject.init()
advanceUntilIdle()
// then
verify something
}
or
@Test
fun `test something`() = runTest {
// given
setup code
// when
subject.init()
// then
advanceUntilIdle()
verify something
}
mbonnin
07/28/2022, 2:04 PMrunTest {}
but not the delay-skipping behaviour? Delays are a part of the behaviour I want to testdmcg
09/09/2022, 8:56 PMhttps://youtu.be/cs2Wu9Co-2s▾
dmcg
09/17/2022, 8:13 AMhttps://youtu.be/i_RqslILYtg▾
dmcg
09/20/2022, 10:57 AMhttps://youtu.be/PnbV1rVI62I▾
Chih Wei Lin
09/24/2022, 2:54 PM@Test
fun `my error test`() {
every { apiManager.foo() }.returnsMany(
Observable.just(Response.error("Error A".toResponseBody())),
Observable.just(Response.error("Error B".toResponseBody())),
Observable.just(Response.error("Error C".toResponseBody())),
)
repeat(3) { presenter.bar() }
verifyOrder {
view.showErrorA()
view.showErrorB()
view.showErrorC()
}
}
Zach Klippenstein (he/him) [MOD]
10/04/2022, 3:09 AMReece H. Dunn
10/22/2022, 6:10 AM@DisplayName
and @Nested
to the kotlin.test core annotations list? I find these annotations useful when writing JUnit tests in Kotlin/JVM.
@DisplayName
-- Because Kotlin/JS does not support spaces in backtick function names, and Kotlin/native does not allow parenthesis having a @DisplayName
annotation allows for a more readable test name (and the ability to specify the class description).
@Nested
-- I often find it useful to use this in my tests, especially to group different partitions or use cases for the thing under test. For example, testing a "to list" or "list of" method with zero, one, and many items.Manuel Lorenzo
10/22/2022, 6:49 PMclass RepositoriesRepositoryImpl @Inject constructor(
@IoCoroutineDispatcher private val ioCoroutineDispatcher: CoroutineDispatcher,
private val service: GithubService,
private val database: RepositoriesDatabase
) : RepositoriesRepository {
@OptIn(ExperimentalPagingApi::class)
override suspend fun fetchRepositories() = withContext(ioCoroutineDispatcher) {
return@withContext Pager(config = PagingConfig(
pageSize = NETWORK_PAGE_SIZE, enablePlaceholders = false
),
remoteMediator = GithubRemoteMediator(ioCoroutineDispatcher, service, database),
pagingSourceFactory = { database.repositoriesDao().allRepositories() }).flow
}
companion object {
const val NETWORK_PAGE_SIZE = 10
}
}
And this is my test class:
@ExperimentalCoroutinesApi
class RepositoriesRepositoryTest {
private lateinit var sut: RepositoriesRepository
private val testDispatcher = UnconfinedTestDispatcher()
private val fakeGithubService: GithubService = mock {
onBlocking { fetchRepos(any(), any()) } doSuspendableAnswer {
Response.success((listOf()))
}
}
private val inMemoryDatabase = Room.inMemoryDatabaseBuilder(
ApplicationProvider.getApplicationContext(), RepositoriesDatabase::class.java
).build()
@Before
fun setup() {
sut = RepositoriesRepositoryImpl(testDispatcher, fakeGithubService, inMemoryDatabase)
}
@Test
fun test1() = runTest {
sut.fetchRepositories().test {
val item: PagingData<Repository> = awaitItem()
assertNull(item)
}
}
}
What I’m trying is to assert the content of the PagingData
, just to see that it contains whatever number repository I’m passing in the test expectation.
How could I do this?
Thanks!Davide Giuseppe Farella
10/27/2022, 5:11 PMsealed interface AffectsA
sealed interface AffectsB
sealed interface Action {
object Act1 : Action, AffectsA
object Act2 : Action, AffectsA, AffectsB
object Act3 : Action, AffectsB
}
and a class like
class Reducer(
private val subReducer1: X,
private val subReducer2: Y
) {
fun reduce(state: State, action: Action): State =
when (action) {
is Act1 -> state.copy(
a = subReducer1.reduce(state.a, action)
)
Act2 -> state.copy(
a = subReducer1.reduce(state.a, action),
b = subReducer2.reduce(state.b, action)
)
Act3 -> state.copy(
b = subReducer2.reduce(state.b, action)
)
}
}
I wanna test that for every action, the correct sub-reducer is called. Something like
reducer.reduce(someState, Act2)
verify {
subReducer1.reduce(someState.a, Act2)
subReducer2.reduce(someState.b, Act2)
}
///
reducer.reduce(someState, Act3)
verify {
subReducer1 wasNot Called
subReducer2.reduce(someState.b, Act2)
}
I usually like to use org.junit.runners.Parameterized
for these cases, but I wanna ensure that all the cases are covered, a.k.a. every sub-type of Action.
Got any idea?radzio
11/14/2022, 1:24 PMkevin.cianfarini
11/15/2022, 5:32 PMPeter Farlow
12/21/2022, 10:26 PMclass ExampleClass(
private val loginApi: LoginApi,
externalScope: CoroutineScope,
) {
private val _loginFlow = MutableSharedFlow<String>()
val loginFlow = _loginFlow.shareIn(externalScope, SharingStarted.Lazily)
suspend fun performLogin(): String {
val result = loginApi.performLogin()
_loginFlow.emit(result)
return result
}
}
interface LoginApi {
suspend fun performLogin(): String
}
I’ve written a test case for this:
class ExampleClassTest {
private val mockApi = mockk<LoginApi> {
coEvery { performLogin() } returns "hello"
}
private val testCoroutineScheduler = UnconfinedTestDispatcher()
private val testScope = TestScope(testCoroutineScheduler)
@Test
fun `this test passes`() = runTest(testCoroutineScheduler) {
val exampleClass = ExampleClass(mockApi, testScope)
expect("hello") {
exampleClass.performLogin()
}
}
}
Can anyone help me understand why calling runTest directly on my TestScope causes this test case to fail with an eventual UncompletedCoroutinesError? The error message says the test coroutine is not completing, and also that there’s an active child job.
@Test
fun `this test times out`() = testScope.runTest {
val exampleClass = ExampleClass(mockApi, testScope)
expect("hello") {
exampleClass.performLogin()
}
}
Peter Farlow
12/22/2022, 3:18 PMTestScope.backgroundScope
. Perhaps this example is more correct:
class ExampleClassTest {
private val mockApi = mockk<LoginApi> { coEvery { performLogin() } returns "hello" }
private val testCoroutineScheduler = UnconfinedTestDispatcher()
private val testScope = TestScope(testCoroutineScheduler)
@Test
fun `this test passes`() = testScope.runTest {
val exampleClass = ExampleClass(mockApi, testScope.backgroundScope)
expect("hello") {
exampleClass.performLogin()
}
}
}
Kwabena Berko
01/21/2023, 1:40 AMdiego-gomez-olvera
02/20/2023, 2:32 PMkotlin.test
besides convenient functions like assertFailsWith, it has inspections to guide devs to use the proper one, which will give more useful error messagesarekolek
02/27/2023, 8:21 PMarekolek
02/27/2023, 8:21 PM