Testing flow combine

huangapple go评论61阅读模式
英文:

Testing flow combine

问题

以下是您要翻译的代码部分:

我正在尝试为我的流程编写一些测试我知道通过手动测试它可以正常工作),但单元测试无法工作

我有这个视图模型

    class TestViewModel(
        customerRepository: CustomerRepository,
    ): ViewModel() {
        private val phoneNumber = MutableStateFlow(customerRepository.getCustomer().phoneNumber)
        private val email = MutableStateFlow(customerRepository.getCustomer().email)
    
        val state: StateFlow<TestContactInformationState> = combine(
            phoneNumber,
            email,
        ) { phoneNumber, email ->
            TestContactInformationState(
                phoneNumber = phoneNumber,
                email = email,
            )
        }.stateIn(
            viewModelScope,
            SharingStarted.WhileSubscribed(),
            TestContactInformationState(
                customerRepository.getCustomer().phoneNumber,
                customerRepository.getCustomer().email,
            ),
        )
    
        fun setPhoneNumber(newPhoneNumber: PhoneNumber?) {
            this.phoneNumber.value = newPhoneNumber
        }
    
        fun setEmail(newEmail: Email?) {
            this.email.value = newEmail
        }
    }
    
    data class TestContactInformationState(
        val phoneNumber: PhoneNumber?,
        val email: Email?,
    )

而且我有这个测试

    
    @Test
    fun `testing stuff`() = runTest {
        val customer = FakeCustomerRepository.fakeCustomer.copy(
            phoneNumber = "+46701234567".toPhoneNumber(),
            email = "hello@mail.com".toEmail(),
        )

        val stateHolder = TestViewModel(
            customerRepository = FakeCustomerRepository(
                fakeCustomer = customer,
            ),
        )

        stateHolder.setPhoneNumber("+46701234568".toPhoneNumber())
        stateHolder.setEmail("fs@sefs.se".toEmail())

        assertEquals("+46701234568".toPhoneNumber(), stateHolder.state.value.phoneNumber)
    }

但它失败并显示以下消息

    期望<+46701234568> 但实际为<+46701234567>
    期望+46701234568
    实际+46701234567

我还尝试过添加 advanceUntilIdle()但没有任何区别
英文:

I'm trying to write some tests for my flow (that I know works by testing it manually), but the unit tests won't work.

I have this view model:

class TestViewModel(
    customerRepository: CustomerRepository,
): ViewModel() {
    private val phoneNumber = MutableStateFlow(customerRepository.getCustomer().phoneNumber)
    private val email = MutableStateFlow(customerRepository.getCustomer().email)

    val state: StateFlow&lt;TestContactInformationState&gt; = combine(
        phoneNumber,
        email,
    ) { phoneNumber, email -&gt;
        TestContactInformationState(
            phoneNumber = phoneNumber,
            email = email,
        )
    }.stateIn(
        viewModelScope,
        SharingStarted.WhileSubscribed(),
        TestContactInformationState(
            customerRepository.getCustomer().phoneNumber,
            customerRepository.getCustomer().email,
        ),
    )

    fun setPhoneNumber(newPhoneNumber: PhoneNumber?) {
        this.phoneNumber.value = newPhoneNumber
    }

    fun setEmail(newEmail: Email?) {
        this.email.value = newEmail
    }
}

data class TestContactInformationState(
    val phoneNumber: PhoneNumber?,
    val email: Email?,
)

And I have this test:

@Test
fun `testing stuff`() = runTest {
    val customer = FakeCustomerRepository.fakeCustomer.copy(
        phoneNumber = &quot;+46701234567&quot;.toPhoneNumber(),
        email = &quot;hello@mail.com&quot;.toEmail(),
    )

    val stateHolder = TestViewModel(
        customerRepository = FakeCustomerRepository(
            fakeCustomer = customer,
        ),
    )

    stateHolder.setPhoneNumber(&quot;+46701234568&quot;.toPhoneNumber())
    stateHolder.setEmail(&quot;fs@sefs.se&quot;.toEmail())

    assertEquals(&quot;+46701234568&quot;.toPhoneNumber(), stateHolder.state.value.phoneNumber)
}

However it fails with this message:

Expected:&lt;+46701234568&gt; but was:&lt;+46701234567&gt;
Expected :+46701234568
Actual   :+46701234567

I have also tried with adding advanceUntilIdle() but that doesn't make any difference

答案1

得分: 2

流程需要被观察。

您在此行直接检查值:

stateHolder.state.value.phoneNumber

相反,您应该像这样做:

stateHolder.state.first()

请注意,first() 是一个挂起函数,因此它需要在您的 runTest{} 块内调用。
first() 正在获取您的流的第一个发射。在测试中有其他有用的选项,例如 .toList() 以获取流的多个发射。

在生产代码中,您不会使用任何这些,只需观察流或收集它。

英文:

Flows need to be observed.

You are checking the value directly in this line

stateHolder.state.value.phoneNumber

Instead, you should do something like this:

stateHolder.state.first()

Notice how first() is a suspend function, therefore it needs to be called within your runTest{} block.
first() is fetching the first emission of your flow. There are other options useful in tests, such as .toList() to fetch several emissions of a flow.

In production code you wouldn't use any of this, simply observe the flow or collect it.

huangapple
  • 本文由 发表于 2023年5月11日 19:17:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76227040.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定