I finally solved my Compose testing problems, afte...
# compose
t
I finally solved my Compose testing problems, after spending quite some time trying to track down some very obscure bugs! With Compose, when testing screens, you call 
composeTestRule.setContent { MyScreen() }
  - if you’ve written Compose UI tests, you’d be familiar with this. If you need to run the tests against a particular activity, for some reason, you can use 
androidComposeTestRule<MyActivity>
In my case, 
MyActivity
 calls 
setContent { MyScreen() }
 during 
onCreate()
. So, what ends up happening, is the test instantiates 
MyActivity
, which calls 
setContent()
, and the screen is composed, with its ViewModel and various dependencies. While this is happening, the test calls its own 
setContent()
 and the screen is composed again, in parallel! This causes all kinds of nightmarish problems. tl;dr Make sure when testing Compose, that you only call 
setContent()
 once per test. And be careful about which 
Activity
 you use to host the test, if you need one!
👀 1
☝️ 1
c
oof. so if my activity already calls setContent, I shouldnt call setContent in my test, right?
t
If your test uses
androidComposeTestRule
, and so runs inside an Activity that already calls
setContent()
, then calling
setContent()
again in your test can cause issues.
So, my advice isn’t ‘don’t call
setContent()
in test’. But rather, don’t test against an Activity that calls
setContent()
My solution was to create another Activity just for test purposes. And, to keep this from prod, I only declare this Activity in the debug AndroidManifest
a
If you don’t need a specific
Activity
, you can use a plain
createComposeRule()
instead along with the
ui-test-manifest
dependency. If you add it with
debugImplementation
, this should function exactly like your test activity:
Copy code
debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")
👍 1
t
Yep. This issue only occurs when you do need a specific Activity, like when you’re injecting stuff via Hilt
👍 1
c
Yeah, I think I need a specific activity because I'm trying to create a few (like 5) critical path end to end tests. So I actually want it to start my app and just assert some basic things.
And so therefore, my end to end test, wouldn't need to call set content, since the activity already calls setConent
t
Yeah. But, when you want to test a Composable in isolation - that’s when you want to be able to call
setContent()
👍 1
So there’s like, this very specific set of circumstances that can lead to a lot of pain 😭
c
"So there’s like, this very specific set of circumstances that can lead to a lot of pain" I think you've summed up software engineering.
😅 1