-
-
Notifications
You must be signed in to change notification settings - Fork 719
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
Robolectric App tests get a closed Koin in composables #1557
Comments
I am experiencing the same issue with koin-androidx-compose:3.4.3. With koin-androidx-compose:3.4.1 + koin-android;3.4.0 everything works fine. The error I get is exactly the same:
|
I experienced this as well in an Android (connected) test. For me the first test that executes is OK, a subsequent one fails. Did some debugging and the root cause seems to be the composition locals that Koin uses, The first time that these composition locals are read, the values are initialized. This means fetching the current Koin application from the default Koin context. All is fine. Before starting the second test (using Only retrieving the Koin application once is fine for production scenarios, but does not work well for tests. I found the same workaround as described in the original issue, so that works for me (outside of Robolectric) as well. Using:
|
We're experiencing this issue in production as well. In one scenario, we need to stop koin, start koin with updated modules and restart the main activity. stopKoin()
startKoin { /* modules */ }
val componentName = ComponentName(context, MainActivity::class.java)
startActivity(Intent.makeRestartActivityTask(componentName)) When creating the new activity, we get the crash when first
Workaround described in the original issue seems to be working for us too. We're using:
|
need to check 👌 |
@jjkester good catch:
I've introduced |
@arnaudgiuliani They run like that for instrumented tests on devices as well (we're not using Robolectric). I do like the Compose API ( As far as I have gathered we're running into some design decision in the compose runtime. The lambda function with which you provide the default value when defining the For us the workaround works fine when testing a whole activity, because we only have to provide a value for the Compose does offer the |
The Koin application is looked up in the Context tree and the Koin CompositionLocals are provided with/from this value. This (still) requires this function to be called around the first time Koin is used from Compose. A practical place for this is the setContent function. This means that (boilerplate) code needs to be added to every Activity or Fragment using Compose, and every test case where a Composable is tested in isolation. Untested - will need verification with these test frameworks! Fixes InsertKoinIOgh-1557
I have had a look at the use cases that Koin has for these To take another direction, I have attempted to create a composable function which will look up the appropriate Koin application and provide it to the composition, based on the workaround we already have in our code and the workaround posted in the first post. It really needs to be tested that it covers all the use cases of Koin, and that it works for the different test frameworks. The first one was not feasible for me to have a look at today (if at all - I will need some pointers!), and the second one would introduce a whole new class of tests to this repository (instrumented tests are not straightforward to run on a CI pipeline) so that does require some thinking (or input from @arnaudgiuliani) before attempting it in my opinion. Code can be found in my fork: jjkester@7bf2a84 |
yes interesting @jjkester the |
Indeed, that function already exists but the difference being that the application already has been defined outside of Compose. The context function has been based on this one from Accompanist, difference being that it is fine to fall back on the application context as that is the root one. |
do you want to make a PR? else I can add it directly. That implies forcing to use |
I'm happy to create a PR. I do have some more ideas though, because as I tried to explain earlier this may not cover all use cases (mainly testing standalone composables using This solution does feel like a workaround, but I'm not confident there is a real, practical solution. (I'm also not confident that there is none at all...). So maybe a bit more investigation is warranted. If I would be contributing the PR I do want to accompany it with a (regression) test suite to show that this indeed solves the issue. Not sure if it is sufficient to try and replicate the behaviour of the test frameworks, or whether it would be better to create actual tests using these actual frameworks. But as I mentioned before, we should consider where to put those and how to run them (especially the Android instrumented tests). Do you have any ideas about that? |
By throwing an exception as default factory for the CompositionLocals we signal that there is no explicit value set. This will trigger the default lookup behavior that used to be the result of the factory function, as long as the appropriate functions getKoin() and getKoinScope() are used. By using the internal Compose API we are able to catch the exception to run the lookup code. We remember the result of the try/catch block to ensure we only incur the overhead of the exception once per `getKoin()` call per composition. Performance analysis and testing necessary! Fixes InsertKoinIOgh-1557
yes, still wondering if it's a "robotelectric" case only of if this has to be part of the API design 🤔 |
@arnaudgiuliani, for us it's not only a robolectric case, see #1557 (comment) |
I am not using Robolectric, so for sure not only an issue with that. Also with the Android Instrumented tests. While running Android tests the application process stays alive, and the |
ok great |
Any news about this? |
still on hold, need to follow up for next release 👍 |
ℹ️ We also have this crash on production. Our workaround is to restart the full process with ProcessPhoenix: |
…Provider to avoid outdated link to Koin scope - Fix #1557
koin-compose 1.1.0 & koin-androidx-compose 3.5.0 will bring KoinContext & KoinAndroidContext to setup compose with the right CompositionLocalProvider, depending on the current context (default context or android one) Let's see how it goes with this. We can replace your snippet with |
Soo, is this fixed? I am trying to |
@mr-kew You need to wrap tests in either the |
@ben-gooding-sky Thanks for quick response. It's working brilliantly.
Should I then wrap my composables inside |
I was also having this issue, and was not using Roboeletric... same as @jjkester Tried KoinContex and KoinAndroidContext wrappers in test without result... so I dig into it and found a probable cause: The Docs indicates this test rule:
This is making subsequent instrumented tests to fail The fix is to use a rule like this:
|
regression spotted in #1900 |
Describe the bug
Using Koin with Robolectric, fails with
When it fails, these return different Koin instances in the composable
To Reproduce
Steps to reproduce the behavior:
** workaround **
In main app composable, override
https://github.com/joreilly/Confetti/pull/580/files#diff-0548d0af1b708341bc3c142fbf71b1270fb90f0653f791f2eea9e92867d2e99f
Expected behavior
Tests should pass as there is a fresh Koin instance for the current test
Koin project used and used version (please complete the following information):
3.4.0
The text was updated successfully, but these errors were encountered: