android studio 3.4
dagger-android 2.19
Я пытаюсь проверить свою активность, и я хочу внедрить макеты в активность из модульного теста с помощью кинжала.
У меня есть простой ForecastActivity
class ForecastActivity : AppCompatActivity() {
@Inject
lateinit var locationUtils: LocationUtils
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
if(locationUtils.isLocationServicesEnabled(this)) {
locationUtils.getLocationCoordinates(this)
}
else {
startRetryFragment()
}
}
}
Проблема в том, что я хочу внедрить макет LocationUtils.
У меня есть модуль кинжала, который возвращает макет для моего юнит-тестирования:
@Module
class ActivityTestModule {
@Reusable
@Provides
fun provideLocationUtils(): LocationUtils = mock()
}
И компонент:
@Singleton
@Component(modules = [ActivityTestModule::class])
interface TestComponent {
fun inject(forecastActivityTest: ForecastActivityTest)
}
У меня есть класс тестового приложения, который расширяет ForecastApplication
class TestApplication : ForecastApplication() {
private lateinit var testComponent: TestComponent
override fun onCreate() {
super.onCreate()
testComponent = DaggerTestComponent
.builder()
.build()
}
fun getTestComponent() = testComponent
}
Для реального модульного теста у меня есть следующее, но есть много ошибок, и код не работает.Я сделал комментарий, где я думаю, что проблемы:
@RunWith(AndroidJUnit4::class)
class ForecastActivityTest {
private lateinit var forecastActivityScenario: ActivityScenario<ForecastActivity>
@Inject
lateinit var locationUtils: LocationUtils
@Before
fun setUp() {
/* Cast error that cannot be cast to a ForecastApplication */
val testApplication = getApplicationContext<ForecastApplication>() as TestApplication
testApplication.getTestComponent()
.inject(this)
forecastActivityScenario = ActivityScenario.launch(ForecastActivity::class.java)
/* Want to stub this locationUtils, as the real implementation passes in instance of the ForecastActivity I don't think will work. Just wondering is it better to use `any()` instead for `isLocationServiceEnabled(any())` */
whenever(locationUtils.isLocationServicesEnabled(any())).thenReturn(true)
forecastActivityScenario.moveToState(Lifecycle.State.DESTROYED)
assertThat(locationUtils).isNotNull
}
@Test
fun `forecastActivityScenario should not be null`() {
assertThat(forecastActivityScenario).isNotNull
forecastActivityScenario = ActivityScenario.launch(ForecastActivity::class.java)
forecastActivityScenario.moveToState(Lifecycle.State.CREATED)
}
}
Я также изменил настройку, чтобы попытаться заставить это работать, используя следующее.Однако фиктивный LocationUtils создается в ForecastActivityTest, но в кинжале ForecastActivity вводится реальная реализация, а не имитатор, который был в модульном тесте, поэтому whenever(locationUtils.isLocationServicesEnabled(any())).thenReturn(true)
работает.
@Before
fun setUp() {
DaggerTestComponent
.builder()
.build()
.inject(this)
forecastActivityScenario = ActivityScenario.launch(ForecastActivity::class.java)
whenever(locationUtils.isLocationServicesEnabled(any())).thenReturn(true)
forecastActivityScenario.moveToState(Lifecycle.State.DESTROYED)
assertThat(locationUtils).isNotNull
}
Большое спасибозаранее,
Я только показал реализацию кинжала со стороны модульного тестирования.В противном случае вопрос будет слишком длинным