https://kotlinlang.org logo
#dagger
Title
# dagger
k

Kevin Worth

03/16/2023, 2:53 PM
Why might injection work just fine in app but not in instrumented tests?
Copy code
import androidx.lifecycle.viewmodel.compose.viewModel
...
@Composable
fun PrimaryScreen(viewModel: PrimaryViewModel = viewModel()) {...}

class PrimaryViewModel @Inject constructor(
    private val jokeRepository: JokeRepository
) : ViewModel() {...}

// app/src/main/java/com/example/jokes/data/di/DataModule.kt
@Module
@InstallIn(SingletonComponent::class)
interface DataModule {

    @Singleton
    @Binds
    fun bindsJokeRepository(
        jokeRepository: DefaultJokeRepository
    ): JokeRepository
...
}

// app/src/androidTest/java/com/example/jokes/testdi/TestDataModule.kt
@Module
@TestInstallIn(
    components = [SingletonComponent::class],
    replaces = [DataModule::class]
)
interface FakeDataModule {

    @Binds
    abstract fun bindRepository(
        fakeRepository: FakeJokeRepository
    ): JokeRepository
...
}

@RunWith(AndroidJUnit4::class)
@HiltAndroidTest
class PrimaryScreenTest {

    var hiltRule = HiltAndroidRule(this)
    val composeTestRule = createAndroidComposeRule<ComponentActivity>()

    @get:Rule
    val rule: RuleChain = RuleChain
        .outerRule(hiltRule)
        .around(composeTestRule)

    @Before
    fun setup() {
        hiltRule.inject()
        composeTestRule.setContent {
            PrimaryScreen()               // Doesn't work
            // PrimaryScreen(viewModel()) // Also doesn't work
        }
    }
When I try to run my tests I get:
Copy code
java.lang.RuntimeException: Cannot create an instance of class com.example.jokes.ui.joke.PrimaryViewModel
    ...
Caused by: java.lang.NoSuchMethodException: com.example.jokes.ui.joke.PrimaryViewModel.<init> []
Any ideas from anyone?
🧵 1
For those playing along at home, this(the following git diff) appears to work around the issue:
Copy code
- fun PrimaryScreen(viewModel: PrimaryViewModel = viewModel()) {

+ fun PrimaryScreen() {
+     val viewModel: PrimaryViewModel = viewModel()
Now I wonder if anyone knows why… (again, with the key point being, if it works in the production code, why not in instrumented tests…)
11 Views