如何使用 Junit 在 Kotlin 中测试函数

How to test a function in Kotlin with Junit

我用 Kotlin 编写程序。该程序运行良好,但我仅使用 运行 程序测试该功能。我想我知道问题出在哪里,但我不知道如何修改测试。提前致谢!

class Dice {
var firstDice = 1
var secondDice = 1
var thirdDice = 3
var fourthDice = 2
var fifthDice = 2
val dices: MutableList<Int> = ArrayList()

fun throwDices() {
    firstDice = Random.nextInt(1,7)
    dices.add(firstDice)
    println("Eldobtad a kockákat, az első kocka értéke: $firstDice")
    secondDice = Random.nextInt(1,7)
    dices.add(secondDice)
    println("A második kocka értéke: $secondDice")
    thirdDice = Random.nextInt(1,7)
    dices.add(thirdDice)
    println("A harmadik kocka értéke: $thirdDice")
    fourthDice = Random.nextInt(1,7)
    dices.add(fourthDice)
    println("A negyedik kocka értéke: $fourthDice")
    fifthDice = Random.nextInt(1,7)
    dices.add(fifthDice)
    println("Az ötödik kocka értéke: $fifthDice")
    dices.sort()
    println(dices)
}

fun winningCheck() :Int {
    if(dices[0] == dices[1] && dices[0] == dices[2] && dices[0] == dices[3] && dices[0] == dices[4] ) {
        return 15
    }
    else if(dices[0] == dices[1] && dices[0] == dices[2] && dices[0] == dices[3]) {
        return  9
    }
    else if (dices[0] == dices[1] && dices[0] == dices[2] && dices[3] == dices[4]) {
        return 5
    }
    else if(dices[0] == dices[1] && dices[0] == dices[2] || dices[1] == dices[2] && dices[1] == dices[3] ||
            dices[2] == dices[3] && dices[2] == dices[4]) {
        return 3
    }
    else if(dices[0] == dices[1] && dices[2] == dices[3] ||
            dices[1] == dices[2] && dices[3] == dices[4] ||
            dices[0] == dices[1] && dices[3] == dices[4]) {
        return  2
    }else if (dices[0] == dices[1] || dices[1] == dices[2] || dices[2] == dices[3] || dices[3] == dices[4]) {
        return 1
    }
    else
        return 0
}

}

这是class,我要测试,这里是测试代码:

class DiceTest {

private val dice = Dice()
private val dices: MutableList<Int> = ArrayList()

@Before
fun init() {
    dice.firstDice = 1
    dice.secondDice = 1
    dice.thirdDice= 1
    dice.fourthDice = 1
    dice.fifthDice = 1

    dices.add(dice.firstDice)
    dices.add(dice.secondDice)
    dices.add(dice.thirdDice)
    dices.add(dice.fourthDice)
    dices.add(dice.fifthDice)
}

@Test
fun checkingFiveOfAKind () {
    assertEquals(15,dice.winningCheck())
}

这是错误代码:

我认为您的示例可以简化为询问,为什么这段代码不起作用:

@Test
fun checkingFiveOfAKind() {
    val dices: MutableList<Int> = ArrayList()
    dices.add(1)
    dices.add(1)
    dices.add(1)
    dices.add(1)
    dices.add(1)
    
    val anotherDices: MutableList<Int> = ArrayList()

    val result :Int
    if(anotherDices[0] == anotherDices[1] 
       && anotherDices[0] == anotherDices[2] 
       && anotherDices[0] == anotherDices[3] 
       && anotherDices[0] == anotherDices[4] ) {
       result = 15
    } else {
       result = 0
    }
 
    assertEquals(15, result)
}

但这段代码确实有效:

@Test
fun checkingFiveOfAKind() {
    val dices: MutableList<Int> = ArrayList()
    dices.add(1)
    dices.add(1)
    dices.add(1)
    dices.add(1)
    dices.add(1)
    
    val result :Int
    if(dices[0] == dices[1] 
       && dices[0] == dices[2] 
       && dices[0] == dices[3] 
       && dices[0] == dices[4] ) {
       result = 15
    } else {
       result = 0
    }
 
    assertEquals(15, result)
}

或者换一种写法:

您正在将掷骰子添加到一个名为 dices 的变量中,但这是在您的测试中声明的,它不是您在 Dice class 中使用的变量,那是另一个列表。

您可以像这样修复您的测试:

class DiceTest {

private val dice = Dice()

@Before
fun init() {
    dice.firstDice = 1
    dice.secondDice = 1
    dice.thirdDice= 1
    dice.fourthDice = 1
    dice.fifthDice = 1

    dice.dices.add(dice.firstDice)
    dice.dices.add(dice.secondDice)
    dice.dices.add(dice.thirdDice)
    dice.dices.add(dice.fourthDice)
    dice.dices.add(dice.fifthDice)
}

@Test
fun checkingFiveOfAKind () {
    assertEquals(15, dice.winningCheck())
}

简单的答案是:

而不是像这样添加骰子:

dices.add(dice.firstDice)

你需要这样添加:

dice.dices.add(dice.firstDice)

因为 winningCheck() 正在检查 Dice class

作为编码最佳实践旁注:

另一种测试骰子的方法 class 是覆盖您试图控制的部分(随机数生成器)。这样您就可以测试 class 的 public 接口,而不是公开字段进行测试。像这样:

interface NumberGenerator {
     fun generate() : Int
}

class RandomNumberGenerator : NumberGenerator {
    override fun generate() {
        return Random.nextInt(1,7)
    }
}

class Dice(private val numberGenerator: NumberGenerator = RandomNumberGenerator()) {
    
    private var firstDice = 1
    private var secondDice = 1
    private var thirdDice = 3
    private var fourthDice = 2
    private var fifthDice = 2
    private val dices: MutableList<Int> = ArrayList()
    
    fun throwDices() {
        firstDice = numberGenerator.generate()
        dices.add(firstDice)
        println("Eldobtad a kockákat, az első kocka értéke: $firstDice")
        secondDice = numberGenerator.generate()
        dices.add(secondDice)
        println("A második kocka értéke: $secondDice")
        thirdDice = numberGenerator.generate()
        dices.add(thirdDice)
        println("A harmadik kocka értéke: $thirdDice")
        fourthDice = numberGenerator.generate()
        dices.add(fourthDice)
        println("A negyedik kocka értéke: $fourthDice")
        fifthDice = numberGenerator.generate()
        dices.add(fifthDice)
        println("Az ötödik kocka értéke: $fifthDice")
        dices.sort()
        println(dices)
    }
    
    fun winningCheck() :Int {
        // Your winning check code here
    }
}

然后在你的测试中:

class TestNumberGenerator(
    private val numbersToReturn: List<Int>,
) : NumberGenerator {
    private var count = 0

    override fun generate() {
        return numbersToReturn.get(count).also {
            if(count == numbersToReturn.size) count = 0 else count++
        }
    }
}


class DiceTest {
    
    @Test
    fun checkingFiveOfAKind () {
        val dice = Dice(TestNumberGenerator(listOf(1, 1, 1, 1, 1)))

        dice.throwDices()

        assertEquals(15, dice.winningCheck())
    }

}

TestNumberGenerator 仍然假定所有骰子都按顺序掷出,并且每个骰子只掷一次,但它会与您当前的代码一起使用,并且它使您的测试更容易理解:-)。