3

我正在尝试使用 MVP 编写一个应用程序,并调整我以前用 Java 编写的异步存储库模式以使用 Kotlin 的挂起函数。但是,我无法正确测试使用挂起函数的代码。我得到的进一步是让测试运行并失败,因为我认为模拟没有返回它应该返回的对象,而是返回 null 。

这是一个显示问题的小应用程序:

UserRepository(该方法getUser()在返回虚拟用户和抛出异常之间交替):

interface UserRepository {
    suspend fun getUser(): User
}

class UserRepositoryImpl : UserRepository {

    var shouldWork = false

    override suspend fun getUser(): User {

        shouldWork = !shouldWork

        if (shouldWork) {
            return User("Mr. User", "user@example.com")
        } else {
            throw UnableToFetchUserInfoException()
        }

    }
}

风景:

interface MainView {
    fun showUserInfo(user: User)
    fun hideUserInfo()
    fun showFailedToLoadUserInfoIndicator()
    fun hideFailedToLoadUserIndicator()
}

class MainActivity : AppCompatActivity(), MainView {

    private lateinit var presenter: MainPresenter

    override fun showUserInfo(user: User) {
        userInfo.text = user.toString()
    }

    override fun hideUserInfo() {
        userInfo.text = ""
    }

    override fun showFailedToLoadUserInfoIndicator() {
        Toast.makeText(this, "Failed to get user info", Toast.LENGTH_SHORT).show()
    }

    override fun hideFailedToLoadUserIndicator() {
        // nothing to do. It's a toast.
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        presenter = MainPresenterImpl(this, UserRepositoryImpl(), UI)

        button.setOnClickListener {
            presenter.onFetchUserButtonClicked()
        }

    }


}

主持人:

interface MainPresenter {
    fun onFetchUserButtonClicked()
}

class MainPresenterImpl(private val view: MainView,
                        private val userRepository: UserRepository,
                        private val coroutineContext: CoroutineContext) : MainPresenter {

    override fun onFetchUserButtonClicked() {
        launch(coroutineContext) {
            view.hideFailedToLoadUserIndicator()
            try {
                val user = userRepository.getUser()
                view.showUserInfo(user)
            } catch (ex: UnableToFetchUserInfoException) {
                view.hideUserInfo()
                view.showFailedToLoadUserInfoIndicator()
            }
        }
    }

}

和测试:

@Test
fun `should show user info on the view when the user request finishes succesfully`() = runBlocking {
    presenter = MainPresenterImpl(viewMock, userRepositoryMock, CommonPool)

    val expectedUser = User("Test", "test@testaing.com")

    whenever(runBlocking { userRepositoryMock.getUser() } ).thenReturn(expectedUser)
    presenter.onFetchUserButtonClicked()
    verify(viewMock, times(1)).showUserInfo(expectedUser)

}

哪个输出...

Argument(s) are different! Wanted:
mainView.showUserInfo(
    User(name=Test, email=test@testaing.com)
);
-> at com.pablobr9.suspendwithtests.MainPresenterImplTest$should show user info on the view when the user request finishes succesfully$1.doResume(MainPresenterImplTest.kt:40)
Actual invocation has different arguments:
mainView.showUserInfo(
    null
);
-> at com.pablobr9.suspendwithtests.MainPresenterImpl$onFetchUserButtonClicked$1.doResume(MainPresenterImpl.kt:15)

我已经尝试了很多东西,但我仍然无法使用 Kotlin 中的挂起函数/协程编写可测试的 MVP 应用程序。连这么简单的一个都做不到。我在这里想念什么?

4

1 回答 1

-2

该修复程序已经在 mockito 库中,https://github.com/nhaarman/mockito-kotlin/pull/171

验证您是否也已mockito-core 明确进入依赖项列表,例如:

dependencies {
    // other dependencies...
    // mockito...
    testImplementation "org.mockito:mockito-core:2.13.0"
    // mockito kotlin...
    testImplementation "com.nhaarman:mockito-kotlin:1.5.0"
}
于 2018-03-10T02:51:53.297 回答