java模拟函数中的私有变量以测试junit4

2uluyalo  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(364)

我正在为一个函数编写一个junit4测试,这个函数有基于其他函数设置的布尔变量。如何在测试用例中模拟这些布尔变量。
我正在测试的功能

private var operatorSigned = false
private var engineerSigned = false

override fun onValidationSucceeded() {
    if (operatorSigned && engineerSigned) {
        sendQualityControlCheck()
    } else {
        view.showToastMessage(app.getString(R.string.quality_control_signatures_not_complete))
    }
}

这就是值的设置方式

override fun signatureSigned(name: String, svgSignature: String, bitmapSignature: Bitmap, signatureType: SignatureType) {
    val svgSignatureGzipped = CompressionTools.gzipCompress(svgSignature)
    when (signatureType) {
        SignatureType.OPERATOR -> {
            operatorSignature = QualityControlSignature(svgSignatureGzipped, DateTime())
            operatorSigned = true
            view.operatorSignatureSigned()
        }
        SignatureType.ENGINEER -> {
            engineerSignature = QualityControlSignature(svgSignatureGzipped, DateTime())
            engineerSigned = true
            engineerName = name
            view.engineerSignatureSigned()
        }
    }
}

我的测试用例

@Test
fun `must show toast message when onValidationSucceeded is called and operatorSigned is false`() {
    `when`(app.getString(R.string.quality_control_signatures_not_complete)).thenReturn("Operator and Engineer signature required")
    presenter.onValidationSucceeded()
    verify(view).showToastMessage("Operator and Engineer signature required")
}

我想能够改变operatorsigned和engineersigned的值,我怎么做呢。

zujrkrfu

zujrkrfu1#

让我们假装 OPERATOR 代码的路径将这些布尔值设置为false:

@Test
fun `must show toast message when onValidationSucceeded is called and signature is Operator`() {
    // Given
    signatureSigned("unusedName", "unusedSig", null, SignatureType.OPERATOR) 
`when`(app.getString(R.string.quality_control_signatures_not_complete)).thenReturn("Operator and Engineer signature required")
    // When
    presenter.onValidationSucceeded()
    // Then
    verify(view).showToastMessage("Operator and Engineer signature required")
}

(不得不假装,因为现在你共享的代码只会将布尔值设为真)。
现在您正在对类行为进行单元测试,而不是测试该行为是如何编码的。例如,现在如果那些布尔值被重构为int值。这次考试你不用碰它也能通过,这是件好事!
或者如果你的代码保持原样。你可以这样测试:

@Test
fun `must show toast message when onValidationSucceeded is called and has not been signature signed`() {
    // Given
    // We haven't signature signed (see verify)
   `when`(app.getString(R.string.quality_control_signatures_not_complete)).thenReturn("Operator and Engineer signature required")
    // When
    presenter.onValidationSucceeded()
    // Then
    verify(view).showToastMessage("Operator and Engineer signature required")
    verify(view, never()).operatorSignatureSigned()
    verify(view, never()).engineerSignatureSigned()
}

如何模拟静态方法(提示您不需要,请将其移动到系统边缘,稍后再考虑)。
你现在的班级:

class MyClass {

    override fun signatureSigned(name: String, svgSignature: String, bitmapSignature: Bitmap, signatureType: SignatureType) {
        val svgSignatureGzipped = CompressionTools.gzipCompress(svgSignature)
        ...
    }

}

所以您需要删除静态调用,对于另一个可以作为依赖项执行静态调用的类。

interface SignatureCompressor {
    fun compress(signature: String)
}

class GZipSignatureCompressor : SignatureCompressor {
    override fun compress(signature: String) {
        return CompressionTools.gzipCompress(signature)
    } 
}

现在你的班级变成:

class MyClass(private val compressor: SignatureCompressor) {

    override fun signatureSigned(name: String, svgSignature: String, bitmapSignature: Bitmap, signatureType: SignatureType) {
        val svgSignatureGzipped = compressor.compress(svgSignature)
        ...
    }

}

你可以模拟压缩机:

val cut = MyClass(mockk())

如果只有一个压缩实现,那么也不需要接口

相关问题