尝试使用匕首在单元测试中存根向活动中注入模拟

时间:2019-05-03 18:00:28

标签: android unit-testing dagger-2 dagger

android studio 3.4
dagger-android 2.19

我正在尝试测试我的Activity,我想使用匕首将模拟从单元测试注入到Activity中。

我有一个简单的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的模拟物。

我有一个Dagger模块,该模块返回用于我的单元测试的模拟:

@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
}

在此先感谢

我仅从单元测试方面展示了匕首实现。否则问题将太长了

0 个答案:

没有答案