Перебор личных переменных в функции для тестирования Junit4 - PullRequest
2 голосов
/ 13 февраля 2020

Я пишу тест 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()
        }
    }
}

Мой тест case

@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, как я могу это сделать.

1 Ответ

2 голосов
/ 13 февраля 2020

Давайте притворимся, что путь 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")
}

(пришлось притворяться, потому что сейчас код, который вы предоставили, только когда-либо устанавливает логические значения в true).

Теперь вы тестируете классы поведение , а не как кодируется это поведение. Например, теперь, если те логические значения, где рефакторинг для значения 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()
}

Как смоделировать метод stati c (намекните, что вы этого не делаете, вы перемещаете его на край своей системы и беспокоитесь об этом позже).

Ваш класс прямо сейчас:

class MyClass {

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

}

Поэтому вам нужно удалить вызов stati c для другого класса, который может выполнять вызов stati c в качестве зависимости.

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())

Вам также не нужен интерфейс, если вы есть только одна реализация сжатия

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...