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())
我正在使用 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())