Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit-Testing with Coroutines results in "You may not call the store from a thread other than the thread on which it was created" #38

Closed
jennymolske opened this issue Feb 3, 2020 · 8 comments

Comments

@jennymolske
Copy link

jennymolske commented Feb 3, 2020

Hi,

we currently use your library in combination with Kotlin Coroutines and Flow. One of our middleware methods looks like this:

private fun agbLoad(store: Store<AppState>, action: AgbLoad, next: Dispatcher) {
        CoroutineScope(Main).launch {
            flow { emit(apiService.client().user().api().termsOfUse()) }
                    .flowOn(IO)
                    // flowOn only works upstream.
                    // Catch & Collect are executed on the main thread
                    .catch { e ->
                        e.printStackTrace()
                        store.dispatch(AgbLoadFailure(e))
                    }
                    .collect { agb -> store.dispatch(AgbLoadSuccess(LegalState.Agb(agb.text, agb.activeFrom.ddMMYYYY()))) }
        }

        next(action)
    }

We wanted to test this (and the other functions) and wrote the following JUnit Test:

    fun setUp() {
        Dispatchers.setMain(mainThreadSurrogate)
        recorderMiddleware = RecorderMiddleware()
        legalMiddleware = LegalMiddleware(apiService(), assetFeatureMock, userServiceMock)
    }
    @Test
    fun agbLoad_dispatchesAgbLoadSuccess() {
        webServer().setDispatcher(object : Dispatcher() {
            override fun dispatch(request: RecordedRequest?): MockResponse {
                return MockResponse().setResponseCode(HttpURLConnection.HTTP_OK).setBody(termsOfUseResponseJson())
            }
        })

        runBlocking {
            CoroutineScope(Main).launch {
                val store = createStore(appReducer, AppState(), applyMiddleware(
                        recorderMiddleware.all, LegalMiddleware(apiService(), assetFeatureMock, userServiceMock).all
                ))

                store.dispatch(AgbLoad())
            }
        }

        Barrier.awaitUntil { recorderMiddleware.getRecordings().size == 2 }
        assertThat(recorderMiddleware.getRecordings().last(), instanceOf(AgbLoadSuccess::class.java))
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher
        mainThreadSurrogate.close()
    }

Unfortunately the test throws an error:
Exception in thread "UI @coroutine#3" java.lang.IllegalStateException: You may not call the store from a thread other than the thread on which it was created. This includes: getState(), dispatch(), subscribe(), and replaceReducer() This store was created on: 'UI @coroutine#2' and current thread is 'UI @coroutine#3' at org.reduxkotlin.CreateStoreKt$createStore$3.invoke(CreateStore.kt:50) at org.reduxkotlin.CreateStoreKt$createStore$7.invoke(CreateStore.kt:174)

I already tried lots of coroutine combinations to get rid of this issue, but no success. Do you have an idea how we can fix this?

(additional information): The exception doesn't appear in production, only in the test scenario.

Thanks for your help :)

@patjackson52
Copy link
Contributor

Interesting. Is this open source anywhere where I can pull it down? I will look into this.

@jennymolske
Copy link
Author

jennymolske commented Feb 4, 2020

It is not open source, but I've created a simplified project which also reproduces the error :)
You can download it from https://drive.google.com/open?id=1Cp1BYtFlFKiQd6X_cftLYA02XOMS-U0D

@jennymolske
Copy link
Author

@patjackson52 Do you had time yet to look into this issue? :)

@patjackson52
Copy link
Contributor

Thanks for pinging and the sample project @jennymolske. Looking into it now and working on a fix. It is a bug with 0.3.1. I would recommend going back to a previous version until I get the next release out (hopefully tomorrow or this weekend)

@patjackson52
Copy link
Contributor

@jennymolske PR is up for this issue. If your interested please review. Will likely merge & release tomorrow if no issues.

patjackson52 added a commit that referenced this issue Feb 23, 2020
* bugfix issue #38 enforce same thread

* bump to v3.2
@patjackson52
Copy link
Contributor

fix available in v0.3.2

@jennymolske
Copy link
Author

Great, thank you :)
If I change the version of the lib to 0.3.2 I get an error saying:
Failed to resolve: org.reduxkotlin:redux-kotlin-jvm:0.3.2

Do you know when the new version will be available?

@patjackson52
Copy link
Contributor

It went live yesterday @jennymolske

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants