Tibor Tóth
Tibor Tóth

Reputation: 129

How to test a function in Kotlin with Junit

I write a program in Kotlin. The program is working fine, but I only test the function with running the program. I think I know what the problem is, but I don't know, how to modiy the test. Thanks in advance!

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
}

}

This is the class, I want to test, and here is the testing code:

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

And here is the error code:

enter image description here

Upvotes: 0

Views: 410

Answers (3)

Blundell
Blundell

Reputation: 76476

As a coding best practice side note:

Another way to test your dice class, would be to override the part you are trying to control (the random number generator). That way you can test the public interface of your class, instead of exposing the fields for testing. Something like this:

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
    }
}

Then in your tests:

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

}

The TestNumberGenerator still assumes that all dice are rolled in order and only once each, but it'll work with your current code, and it makes your test much more understandable :-).

Upvotes: 1

Shailendra Madda
Shailendra Madda

Reputation: 21551

The simple answer is:

instead of adding dices like this:

dices.add(dice.firstDice)

you need to add like this:

dice.dices.add(dice.firstDice)

As winningCheck() is checking inside the Dice class

Upvotes: 1

Blundell
Blundell

Reputation: 76476

I think your example could be simplified to ask, why does't this code work:

@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)
}

But this code does work:

@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)
}

Or written another way:

You are adding your dice rolls to a variable called dices but this is a declared in your test, it is not the variable you are using inside your Dice class, that is another List.

You may be able to fix your test like this:

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

Upvotes: 1

Related Questions