使用捕获和模拟对类进行单元测试

ant*_*009 5 android unit-testing kotlin

我正在尝试对以下类进行单元测试:

class UserProfileDetailsAnalyticUseCaseImp @Inject constructor(private val analyticsProvider: AnalyticsProvider) : UserProfileDetailsAnalyticUseCase {
    override fun execute(cdsCustomer: CDSCustomer) {
        with(analyticsProvider) {
            log(AnalyticEvent.UserId(cdsCustomer.id.toString()))
            log(AnalyticEvent.UserEmail(cdsCustomer.email))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的单元测试:

class UserProfileDetailsAnalyticUseCaseImpTest {

    private lateinit var userProfileDetailsAnalyticUseCaseImp: UserProfileDetailsAnalyticUseCaseImp
    private val analyticsProviders: AnalyticsProvider = mock()


    @Before
    fun setUp() {
        userProfileDetailsAnalyticUseCaseImp = UserProfileDetailsAnalyticUseCaseImp(analyticsProviders)
    }

    @Test
    fun `should send analytic event`() {
        // Arrange
        val cdsCustomer = CDSCustomer(
            id = Random.nextInt(0, 100000),
            email = UUID.randomUUID().toString())

        val userIdCapture= argumentCaptor<AnalyticEvent.UserId>()
        val userEmailCapture= argumentCaptor<AnalyticEvent.UserEmail>()

        // Act
        userProfileDetailsAnalyticUseCaseImp.execute(cdsCustomer)

        // Assert
        verify(analyticsProviders, atLeastOnce()).log(userIdCapture.capture())
        verify(analyticsProviders, atLeastOnce()).log(userEmailCapture.capture())
    
        assertThat(userIdCapture.firstValue.userId).isEqualTo(cdsCustomer.id.toString())
        assertThat(userEmailCapture.firstValue.email).isEqualTo(cdsCustomer.email)
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误如下:

AnalyticEvent$UserId cannot be cast to AnalyticEvent$UserEmail
Run Code Online (Sandbox Code Playgroud)

我怀疑是因为被测类正在为每个类创建一个新对象 log方法所以它们对于单元测试中已验证的方法不会相同

IE log(AnalyticEvent.UserId(cdsCustomer.id.toString()))

作为一个新的AnaltyicEvent.UserId将被创建并且只是为了同一个AnalyticProvider模拟

非常感谢您的任何建议

luk*_*jar 3

在的文档ArgumentCaptor我们可以读到:

该实用程序类不执行任何类型检查。通用签名只是为了避免在代码中进行强制转换。

此外,用于收集捕获参数的CapturingMatcher有一个匹配所有对象的方法:

public boolean matches(Object argument) {
    return true;
}
Run Code Online (Sandbox Code Playgroud)

这意味着这是正常行为,即使我们指定捕获器的具体类型,它也会记录传递的所有参数。当然,所有这些参数都必须继承自同一个基类,因为在其他情况下capture方法将导致编译错误。

因此,两名绑架者都记录了两个论点。

要修复测试的类转换异常,您可以为电子邮件断言secondaryValue

assertThat(userEmailCapture.secondValue.email).isEqualTo(cdsCustomer.email) 
Run Code Online (Sandbox Code Playgroud)

您还可以停止使用参数捕获器并简单地验证方法的调用log

verify(analyticsProviders).log(AnalyticEvent.UserId(cdsCustomer.id.toString()))
verify(analyticsProviders).log(AnalyticEvent.UserEmail(cdsCustomer.email))
Run Code Online (Sandbox Code Playgroud)