Unit testing a Kotlin coroutine with delay - android

I'm trying to unit test a Kotlin coroutine that uses delay(). For the unit test I don't care about the delay(), it's just slowing the test down. I'd like to run the test in some way that doesn't actually delay when delay() is called.
I tried running the coroutine using a custom context which delegates to CommonPool:
class TestUiContext : CoroutineDispatcher(), Delay {
suspend override fun delay(time: Long, unit: TimeUnit) {
// I'd like it to call this
}
override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
// but instead it calls this
}
override fun dispatch(context: CoroutineContext, block: Runnable) {
CommonPool.dispatch(context, block)
}
}
I was hoping I could just return from my context's delay() method, but instead it's calling my scheduleResumeAfterDelay() method, and I don't know how to delegate that to the default scheduler.

If you don't want any delay, why don't you simply resume the continuation in the schedule call?:
class TestUiContext : CoroutineDispatcher(), Delay {
override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
continuation.resume(Unit)
}
override fun dispatch(context: CoroutineContext, block: Runnable) {
//CommonPool.dispatch(context, block) // dispatch on CommonPool
block.run() // dispatch on calling thread
}
}
That way delay() will resume with no delay. Note that this still suspends at delay, so other coroutines can still run (like yield())
#Test
fun `test with delay`() {
runBlocking(TestUiContext()) {
launch { println("launched") }
println("start")
delay(5000)
println("stop")
}
}
Runs without delay and prints:
start
launched
stop
EDIT:
You can control where the continuation is run by customizing the dispatch function.

In kotlinx.coroutines v1.6.0 the kotlinx-coroutines-test module was updated. It allows tests to use the runTest() method and TestScope to test suspending code, automatically skipping delays.
See the documentation for details on how to use the module.
Previous Answer
In kotlinx.coroutines v1.2.1 they added the kotlinx-coroutines-test module. It includes the runBlockingTest coroutine builder, as well as a TestCoroutineScope and TestCoroutineDispatcher. They allow auto-advancing time, as well as explicitly controlling time for testing coroutines with delay.

Use TestCoroutineDispatcher, TestCoroutineScope, or Delay
TestCoroutineDispatcher, TestCoroutineScope, or Delay can be used to handle a delay in a Kotlin coroutine made in the production code tested.
Implement
In this case SomeViewModel's view state is being tested. In the ERROR state a view state is emitted with the error value being true. After the defined Snackbar time length has passed using a delay a new view state is emitted with the error value set to false.
SomeViewModel.kt
private fun loadNetwork() {
repository.getData(...).onEach {
when (it.status) {
LOADING -> ...
SUCCESS ...
ERROR -> {
_viewState.value = FeedViewState.SomeFeedViewState(
isLoading = false,
feed = it.data,
isError = true
)
delay(SNACKBAR_LENGTH)
_viewState.value = FeedViewState.SomeFeedViewState(
isLoading = false,
feed = it.data,
isError = false
)
}
}
}.launchIn(coroutineScope)
}
There are numerous ways to handle the delay. advanceUntilIdle is good because it doesn't require specifying a hardcoded length. Also, if injecting the TestCoroutineDispatcher, as outlined by Craig Russell, this will be handled by the same dispatcher used inside of the ViewModel.
SomeTest.kt
private val testDispatcher = TestCoroutineDispatcher()
private val testScope = TestCoroutineScope(testDispatcher)
// Code that initiates the ViewModel emission of the view state(s) here.
testDispatcher.advanceUntilIdle()
These will also work:
testScope.advanceUntilIdle()
testDispatcher.delay(SNACKBAR_LENGTH)
delay(SNACKBAR_LENGTH)
testDispatcher.resumeDispatcher()
testScope.resumeDispatcher()
testDispatcher.advanceTimeBy(SNACKBAR_LENGTH)
testScope.advanceTimeBy(SNACKBAR_LENGTH)
Error without handling the delay
kotlinx.coroutines.test.UncompletedCoroutinesError: Unfinished coroutines during teardown. Ensure all coroutines are completed or cancelled by your test.
at kotlinx.coroutines.test.TestCoroutineDispatcher.cleanupTestCoroutines(TestCoroutineDispatcher.kt:178)
at app.topcafes.FeedTest.cleanUpTest(FeedTest.kt:127)
at app.topcafes.FeedTest.access$cleanUpTest(FeedTest.kt:28)
at app.topcafes.FeedTest$topCafesTest$1.invokeSuspend(FeedTest.kt:106)
at app.topcafes.FeedTest$topCafesTest$1.invoke(FeedTest.kt)
at kotlinx.coroutines.test.TestBuildersKt$runBlockingTest$deferred$1.invokeSuspend(TestBuilders.kt:50)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.test.TestCoroutineDispatcher.dispatch(TestCoroutineDispatcher.kt:50)
at kotlinx.coroutines.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:288)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:109)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:158)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.async(Builders.common.kt:91)
at kotlinx.coroutines.BuildersKt.async(Unknown Source)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.async$default(Builders.common.kt:84)
at kotlinx.coroutines.BuildersKt.async$default(Unknown Source)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:49)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:80)
at app.topcafes.FeedTest.topCafesTest(FeedTest.kt:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

In kotlinx.coroutines v0.23.0 they introduced a TestCoroutineContext.
Pro: it makes truly testing coroutines with delay possible. You can set the CoroutineContext's virtual clock to a moment in time and verify the expected behavior.
Con: if your coroutine code doesn't use delay, and you just want it to execute synchronously on the calling thread, it is slightly more cumbersome to use than the TestUiContext from #bj0's answer (you need to call triggerActions() on the TestCoroutineContext to get the coroutine to execute).
Sidenote:
The TestCoroutineContext now lives in the kotlinx-coroutines-test module starting with coroutines version 1.2.1, and will be marked deprecated or not exist in the standard coroutine library in versions above this version.

Related

kotlinx.coroutines.test the latest API usage

I am working on a test case for ViewModel classes with the recent coroutines-test API and it doesn't work as expected.
#Test
fun `when balanceOf() is called with existing parameter model state is updated with correct value`() = runTest {
Dispatchers.setMain(StandardTestDispatcher())
fakeWalletRepository.setPositiveBalanceOfResponse()
assertThat("Model balance is not default", subj.uiState.value.wallet.getBalance().toInt() == 0)
assertThat("Errors queue is not empty", subj.uiState.value.errors.isEmpty())
assertThat("State is not default", subj.uiState.value.status == Status.NONE)
subj.balanceOf("0x6f1d841afce211dAead45e6109895c20f8ee92f0")
advanceUntilIdle()
assertThat("Model balance is not updated with correct value", subj.uiState.value.wallet.getBalance().toLong() == 42L)
assertThat("Errors queue is not empty", subj.uiState.value.errors.isEmpty())
assertThat("State is not set as BALANCE", subj.uiState.value.status == Status.BALANCE)
}
he issue is not working stably - usually it fails, under debugger usually it passes.
Based on my understanding StandartTestDispatcher shouldn't run coroutines until advanceUntilIdle call when UnconfinedTestDispatcher run them immediately. advanceUntilIdle should wait until all coroutines are finished, but it seems there is a race condition in the next assertThat() call which causes ambiguity in the behaviour of my test case.
advanceUntilIdle should guarantee all coroutines end their work. Does it mean race condition occurs somewhere under .collect{} or state.update {} calls? (In my understanding advanceUntilIdle should wait end of their execution too)
fun balanceOf(owner: String) {
logger.d("[start] balanceOf()")
viewModelScope.launch {
repository.balanceOf(owner)
.flowOn(Dispatchers.IO)
.collect { value ->
logger.d("collect get balance result")
processBalanceOfResponse(value)
}
}
logger.d("[end] balanceOf()")
}
state.update {
it.wallet.setBalance(value.data)
it.copy(wallet = it.wallet, status = Status.BALANCE)
}
From what i see the balanceOf() is executed on the IO dispatcher and you collect in the viewModelScope (which is the Main.Immediate dispatcher). The IO dispatcher is not overridden in your test and this is what causes the unpredictability of your test.
As there’s currently no way to override the IO dispatcher like with setMain, you can add the ability to override the background dispatcher in your ViewModel by adding a default argument, for example :
ViewModel(private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO)
And replace it in your code :
fun balanceOf(owner: String) {
logger.d("[start] balanceOf()")
viewModelScope.launch {
repository.balanceOf(owner)
.flowOn(backgroundDispatcher)
.collect { value ->
logger.d("collect get balance result")
processBalanceOfResponse(value)
}
}
logger.d("[end] balanceOf()")
}
Then in your test you instantiate the ViewModel with the standard test dispatcher and it should work. You can check this page to understand the issue : https://developer.android.com/kotlin/coroutines/test#injecting-test-dispatchers

Flow.collect blocking the main thread

I've the following code that seems to blocking the main thread even though the flow is called on IO coroutine. I'm a kotlin and flow noob. What am I doing wrong here that's blocking the main thread?
Repository:
fun observeData(): Flow<Data> {
return flow {
//third party api is getting data from a ContentProvider
ThirdPartyApi.getData().map { convertFromExternalModelToDataModel(it) }
.collect {
emit(it)
}
}
}
ViewModel:
fun updateUI() {
scope.launch(Dispatchers.IO) {
repository.observerData().collect {
withContext(Dispatchers.Main) {
textView.text = data.name
}
}
}
}
Upon running the following code it I see logs from Android Choreographer "Skipped 200 frames. App is going too much work on main thread"
To collect the data stream with Kotlin Flows as they're emitted, use collect. And as collect is a suspending function, it needs to be executed within a coroutine. It takes a lambda as a parameter that is called on every new value. Since it's a suspend function, the coroutine that calls collect may suspend until the flow is closed.
And you shouldn't be updating your UI inside a ViewModel.
In this case we collect flow inside an activity's lifecycle scope that is main safe and has activity's lifecycle awareness.
And to make our service or repository to execute in a different CouroutineContext, use the intermediate operator flowOn.
flowOn changes the CoroutineContext of the upstream flow, meaning the producer and any intermediate operators applied before (or above) flowOn.
The downstream flow (the intermediate operators after flowOn along with the consumer) is not affected and executes on the CoroutineContext used to collect from the flow.
ViewModel:
fun getData():Flow<Data> = repository.observeData() // Execute on the io dispatcher
// flowOn affects the upstream flow ↑
.flowOn(Dispatchers.IO)
// the downstream flow ↓ is not affected
.catch { exception -> // Executes in the consumer's context
emit(Data())
}
Activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch { // Consumer's context
viewModel.getData().collect { // Suspended
textView.text = data.name // Collect on consumer's context
}
}
}

kotlinx-coroutines-test. withContext {...} in liveData {...} doesn't switch back to the previous context after its finish

I'm writing an integration test for my Android app. And I've faced an issue with liveData {...} coroutine builder: when I call withContext {...} function inside of it, it switches to a given context (e.g. Dispatchers.IO), but does not switch back after return (to Dispatchers.Main.immediate).
The test looks like:
WordFragmentIntegrationTest:
#RunWith(RobolectricTestRunner::class)
#Config(application = TestAppWithDaggerComponent::class)
class WordFragmentIntegrationTest {
#get:Rule
val coroutinesRule = CoroutinesRule()
private val mockWebServer = MockWebServer()
#After
fun teardown() {
mockWebServer.shutdown()
}
#Test
fun `should fetch a word from api and populate the view`() = runBlockingTest {
// Mock api response, it works fine.
val response = MockResponse().setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(SAMPLE_API_WORD_JSON)
.setBodyDelay(0, TimeUnit.MILLISECONDS)
mockWebServer.enqueue(response)
mockWebServer.start(8080)
// Launch a Fragment under test. It triggers an api call.
val fragmentScenario = launchFragmentInContainer<WordFragment>()
// Wait for the Fragment to do its work.
fragmentScenario.onFragment { fragmentUnderTest ->
runBlocking {
while (fragmentUnderTest.isLoading) { yield() }
// Do some assertions...
}
}
}
}
CoroutinesRule:
class CoroutinesRule : ExternalResource() {
override fun before() {
Dispatchers.setMain(TestCoroutineDispatcher())
}
override fun after() {
Dispatchers.resetMain()
}
}
And a piece of code, which causes test failure.
WordViewModel:
val wordLiveData = liveData {
printCurrentThread("Emitting the first value")
emit(UIState.ShowLoading)
val value = withContext(Dispatchers.IO) {
printCurrentThread("Fetching a value")
loadWordUseCase(wordId)
}
printCurrentThread("Emitting the second value")
emit(value)
}
private fun printCurrentThread(message: String) {
val threadInfo = "Thread: ${Thread.currentThread().id}. UI thread: ${Looper.getMainLooper().thread.id}"
println("$message. $threadInfo")
}
It works fine in production environment:
Emitting the first value. Thread: 1. UI thread: 1 # First emitting is on the UI thread.
Fetching a value. Thread: 365. UI thread: 1 # Fetching is on some IO thread.
Emitting the second value. Thread: 1. UI thread: 1 # Switched back to the UI thread.
But in the test environment (where Dispatchers.Main is replaced) withContext {...} does not switch back to liveData {...}'s Dispatchers.Main.immediate, and it causes CoroutineLiveData crash, because its emit() should be called from the UI thread.
Emitting the first value. Thread: 11. UI thread: 11 # Emitted on the UI thread.
Fetching a value. Thread: 19. UI thread: 11 # Switched to IO thread.
Emitting the second value. Thread: 19. UI thread: 11 # Didn't switch back, which caused:
Exception in thread "DefaultDispatcher-worker-1 #coroutine#2"
java.lang.IllegalStateException: Cannot invoke setValue on a background thread
at androidx.lifecycle.LiveData.assertMainThread(LiveData.java:462)
at androidx.lifecycle.LiveData.setValue(LiveData.java:304)
...
Is it a bug or am I doing something wrong? E.g. maybe I have a wrong CoroutinesRule?
That is because the TestCoroutineDispatcher does not switch back to a specific thread like android's Dispatchers.Main does. Instead it behaves similar to Dispatchers.Unconfined.
I am not sure whether this will work with Robolectric, but what worked in unit tests was this:
Add the InstantTaskExecutorRule to your test like you did with your CoroutinesRule. e.g. :
#get:Rule
val executorRule = InstantTaskExecutorRule()
This will allow calling LiveData.setValue(...) on any thread.
Since emit eventually just delegates to setValue, there is no need to adjust your ViewModel code
If the rule is not already available, add this dependency:
testImplementation 'androidx.arch.core:core-testing:2.1.0'
If that still doesnt help, I would like to know what happens if you do not replace the Main dispatcher

Correct way to suspend coroutine until Task<T> is complete

I've recently dove into Kotlin coroutines
Since I use a lot of Google's libraries, most of the jobs is done inside Task class
Currently I'm using this extension to suspend coroutine
suspend fun <T> awaitTask(task: Task<T>): T = suspendCoroutine { continuation ->
task.addOnCompleteListener { task ->
if (task.isSuccessful) {
continuation.resume(task.result)
} else {
continuation.resumeWithException(task.exception!!)
}
}
}
But recently I've seen usage like this
suspend fun <T> awaitTask(task: Task<T>): T = suspendCoroutine { continuation ->
try {
val result = Tasks.await(task)
continuation.resume(result)
} catch (e: Exception) {
continuation.resumeWithException(e)
}
}
Is there any difference, and which one is correct?
UPD: second example isn't working, idk why
The block of code passed to suspendCoroutine { ... } should not block a thread that it is being invoked on, allowing the coroutine to be suspended. This way, the actual thread can be used for other tasks. This is a key feature that allows Kotlin coroutines to scale and to run multiple coroutines even on the single UI thread.
The first example does it correctly, because it invokes task.addOnCompleteListener (see docs) (which just adds a listener and returns immediately. That is why the first one works properly.
The second example uses Tasks.await(task) (see docs) which blocks the thread that it is being invoked on and does not return until the task is complete, so it does not allow coroutine to be properly suspended.
One of the ways to wait for a Task to complete using Kotlin Coroutines is to convert the Task object into a Deferred object by applying Task.asDeferred extension function. For example for fetching data from Firebase Database it can look like the following:
suspend fun makeRequest() {
val task: Task<DataSnapshot> = FirebaseDatabase.getInstance().reference.get()
val deferred: Deferred<DataSnapshot> = task.asDeferred()
val data: Iterable<DataSnapshot> = deferred.await().children
// ... use data
}
Dependency for Task.asDeferred():
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.2'
To call suspend function we need to launch a coroutine:
someCoroutineScope.launch {
makeRequest()
}
someCoroutineScope is a CoroutineScope instance. In android it can be viewModelScope in ViewModel class and lifecycleScope in Activity or Fragment, or some custom CoroutineScope instance. Dependencies:
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'

doReturn doesn't act as proxy but calls my method

I'm implementing some Unit testing in my app and I have a dependency that relies in the Application context. That dependency returns a list of Item but I want to mock that logic to return whatever I want.
I already know the difference between:
a) when(foo.method1()).return(bar)
b) doReturn(bar).when(foo).method1()
(b) shouldn't invoke the method.
Now I have a method called in ItemHelper.kt :
fun retrieveItems(): MutableList<Item> {
val boxStore = BoxStore.getInstance().getBoxFor(Item::class.java)
return boxStore.all
}
and that .getInstance() relies on the Application.
Since I want to mock it, this is my test:
class ItemHelperTests {
#JvmField
#Rule
var mockitoRule = MockitoJUnit.rule()!!
#Mock
private lateinit var itemHelper: ItemHelper
#Test
fun itemsNumber_Test() {
Mockito.doReturn(ArrayList<Item>()).`when`(itemHelper).retrieveItems()
System.out.println("this line is unreachable")
}
}
but that ends calling my code:
java.lang.Exception: Please init BoxStore.boxStore in the MainApplication
at com.example.dependencies.coreData.BoxStore$Companion.throwBoxStoreNotInitialized(BoxStore.kt:33)
at com.example.dependencies.coreData.BoxStore$Companion.getInstance(BoxStore.kt:26)
at com.example.helpers.coreData.Item.ItemHelper.retrieveItems(ItemHelper.kt:20)
at com.example.helpers.ItemHelperTests.itemsNumber_Test(ItemHelperTests.kt:27)
so that method is called, I just want to retrieve an empty ArrayList() when that method is called from JVM.
EDIT
When using #RunWith(MockitoJUnitRunner::class)
I get the same error, but I get one more line of Mockito error:
java.lang.Exception: Please init BoxStore.boxStore in the MainApplication
at com.example.dependencies.coreData.BoxStore$Companion.throwBoxStoreNotInitialized(BoxStore.kt:33)
at com.example.dependencies.coreData.BoxStore$Companion.getInstance(BoxStore.kt:26)
at com.example.helpers.coreData.Item.ItemHelper.retrieveItems(ItemHelper.kt:20)
at com.example.helpers.ItemHelperTests.itemsNumber_Test(ItemHelperTests.kt:27)
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.example.helpers.ItemHelperTests.itemsNumber_Test(ItemHelperTests.kt:27)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
at org.mockito.internal.runners.DefaultInternalRunner$1$1.testFinished(DefaultInternalRunner.java:69)
at org.junit.runner.notification.SynchronizedRunListener.testFinished(SynchronizedRunListener.java:56)
at org.junit.runner.notification.RunNotifier$7.notifyListener(RunNotifier.java:190)
at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:72)
at org.junit.runner.notification.RunNotifier.fireTestFinished(RunNotifier.java:187)
at org.junit.internal.runners.model.EachTestNotifier.fireTestFinished(EachTestNotifier.java:38)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:331)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:78)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:84)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:161)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
In Kotlin every class and method is closed.
I had to define open before retrieveItems(), remaining:
open fun retrieveItems(): MutableList<Item> {
val boxStore = BoxStore.getInstance().getBoxFor(Item::class.java)
return boxStore.all
}

Categories

Resources