Android 集成测试:使用 Dagger 和 Mockito 在 activity 中模拟逻辑/方法,并在测试中获取返回值

Android Integration test: Mocking the logic/ method in within an activity using Dagger and Mockito and get the returned value back within the test

我正在使用 Kotlin 开发 Android 应用程序。我还在使用 Dagger 和 Expresso 为我的应用程序编写集成测试。我现在在模拟逻辑时遇到问题。首先,让我向您展示我如何使用 Dagger 在代码中模拟逻辑以进行集成测试。

我有用于测试的 Dagger 应用程序组件 class 具有以下定义

@Singleton
@Component(modules = [ TestAppModule::class ])
interface TestAppComponent : AppComponent //App component is the actual class used for the application
{
    fun inject(app: MainActivity)
}

这是 TestAppModule 的定义class

@Module
open class TestAppModule (private val app: Application) {
    @Singleton
    @Provides
    open fun fileIOService(): IFileIOService {
        return FakeFileIOService()
    }
}

我还有一个名为 AppModule 的 class 用于具有以下定义的实际应用程序代码。

@Module
open class TestAppModule (private val app: Application) {
    @Singleton
    @Provides
    open fun fileIOService(): IFileIOService {
        return FakeFileIOService()
    }
}

想法是集成测试将使用 TestAppModule,因此将注入 FakeFileIOService class。对于实际应用程序,它将使用 AppModule,因此将注入 FileIOService class。 FakeFileIOService class 和 FileIOService class 都继承自 IFileIOService 接口。 IFileIOService 接口将具有以下定义。

interface IFileIOService
{
    fun saveFile(data: String)
}

FileIOService class 和 FakeIOService class 将有自己的 saveFile 方法实现版本。 FakeIOService 将具有模拟版本。

我将在 MainActivity class 中为 IFileIOService 提供一个 属性 用于依赖注入。

class MainActivity: AppCompatActivity()
{
    @Inject
    lateinit var fileIOService: IFileIOService
}

正如我提到的,FakeFileIOService class 将被注入用于集成测试。该代码工作正常。它为集成测试使用假版本,为实际应用程序使用具体版本。

但是现在,我遇到了一个问题,我需要使用 Mockito 模拟方法的逻辑并在测试中获取返回值。

但是,现在我在使用 Mokito 模拟逻辑来测试 File 并在测试中取回模拟值时遇到问题。

以下是我的

的实现
fun saveFile(data: String) {
    FileOutputStream mockFos = Mockito.mock(FileOutputStream.class);
    mockFos.write(data.getBytes());
    mockFos.close();
}

从字面上看,我正在尝试使用 Mockito 模拟文件逻辑。然后我正在尝试编写类似这样的集成测试。

@get:Rule
var mainActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule<MainActivity>(CameraActivity::class.java, true, false)

@Test
fun fileIsSaveInWhenButtonIsClicked() {
    Intents.init()
    var targetContext: Context = InstrumentationRegistry.getInstrumentation().targetContext
    var intent: Intent = Intent(targetContext, MainActivity::class.java)
    this.mainActivityRule.launchActivity(null) 
    onView(withId(R.id.button_save_file)).perform(click())

    //here I want to assert if the file is saved using Mockito something like this
    //verify(mockFos).write(data.getBytes()); the issue is that I cannot get the mockFos instance creatd in the saveFile method of the FakeFileIOService class
    Intents.release()
}

查看评论中的测试。问题是我想验证文件是否使用 Mockito 保存。但问题是我无法获取在 FakeIOService class 的 saveFile 中创建的 mockFos 实例。我怎样才能测试它?测试这种情况的最佳方法是什么?

您不应该模拟系统逻辑。写入文件和关闭文件是系统逻辑。你只应该嘲笑你自己的逻辑。

您应该验证的是调用了 saveFile 方法。并不是调用了 saveMyFile 的内容。

val mock = mock(IFileIOService::class.java)
mainActivity.fileIOService = mock

//do something that in return does fileIOService.saveFile

verify(mock).saveFile(any())

另一种选择是监视:

 val spy = spy(mainActivity.fileIOService)
 //do something that in return does fileIOService.saveFile

 verify(spy).saveFile(any())