Android -协同程序主调度程序的单元测试失败

dohp0rv5  于 2023-03-11  发布在  Android
关注(0)|答案(1)|浏览(122)

你好,我有一段运行协程的代码。我正在尝试为它编写单元测试。但似乎失败了。我已经添加了协程测试规则来添加StandardTestDispatcher,但我猜这似乎不起作用。任何想法都非常感谢。我第一次尝试为协程编写单元测试,但卡住了。
下面是我的简单演示者类,它使用协程

class PostsActivityPresenter(
    private val apiHelper: ApiFactory
) : CoroutineScope, PostsContract.Presenter {

    private var view:  PostsContract.View? = null

    private val job: Job = Job()
    override val coroutineContext: CoroutineContext = job + Dispatchers.IO

    override fun attachView(view: PostsContract.View?) {
        this.view = view
    }

    override fun getPostsandUserInfo() {
        launch {
            val posts = apiHelper.getPosts()
            val users = apiHelper.getUsers()

            val postsWithUserDetails = mutableListOf<PostsWithUserInfo>()
            for (post in posts) {
                users.firstOrNull { it.id == post.userId }?.let { user ->
                    postsWithUserDetails.add(PostsWithUserInfo(post, user))
                }
            }
            withContext(Dispatchers.Main) {  ///// Test will pass if this line is removed. 
                view?.displayPosts(postsWithUserDetails)
            }
        }

    }

    override fun detachView() {
        job.cancel()
        view = null
    }
}

下面是我单元测试代码:

class PostsPresenterTest {

    @RelaxedMockK
    private lateinit var apiHelper: ApiHelper

    @io.mockk.impl.annotations.MockK
    private lateinit var view: PostsContract.View

    @ExperimentalCoroutinesApi
    @get:Rule
    var coroutinesTestRule = CoroutineTestRule()

    private lateinit var subject: PostsActivityPresenter

    private val posts = listOf(
        Post(
            id = 1,
            userId = 12,
            title = "title 1",
            body = "body 1"
        )
    )

    private val users = listOf(
        User(
            name = "Name1",
            username = "Username1",
            email = "email1@gmail.com",
            id = 12
        ),
        User(
            name = "Name2",
            username = "Username2",
            email = "email2@gmail.com",
            id = 13
        )
    )

    @Before
    fun setUp() {
        MockKAnnotations.init(this, relaxed = true)
        subject = PostsActivityPresenter((apiHelper))
    }

    @ExperimentalCoroutinesApi
    @Test
    fun `test if posts is being called`() = runBlocking {
        // arrange
        coEvery { apiHelper.getPosts() }.returns(posts)
        coEvery { apiHelper.getUsers() }.returns(users)
        every { view.displayPosts(any()) }.returns(Unit)

        // act
        subject.attachView(view)
        subject.getPostsandUserInfo()

        // assert
        coVerify {
            view.displayPosts(
                listOf(
                    PostsWithUserInfo(
                        post = Post(
                            userId = 12,
                            id = 1,
                            title = "title 1",
                            body = "body 1"
                        ),
                        user = User(
                            id = 12,
                            name = "Name1",
                            username = "Username1",
                            email = "email1@gmail.com",
                        )
                    )
                )
            )
        }
    }
}

@ExperimentalCoroutinesApi
class CoroutineTestRule(private val testDispatcher: TestDispatcher = StandardTestDispatcher()) : TestWatcher() {
    override fun starting(description: Description) {
        super.starting(description)
        Dispatchers.setMain(testDispatcher)
    }

    override fun finished(description: Description) {
        super.finished(description)
        Dispatchers.resetMain()
        testDispatcher.cleanupTestCoroutines()
    }
}
jdgnovmf

jdgnovmf1#

将你的测试调度器= StandardTestDispatcher()改为testCoroutineDispatcher = UnconfinedTestDispatcher(),这对我来说非常有效。

相关问题