DEV Community

loading...
Cover image for Assertion vs Assumption when writing tests (JUnit)

Assertion vs Assumption when writing tests (JUnit)

amaralani profile image Amir Maralani Updated on ・2 min read

Most of the developers are familiar with the concept of assertion in test writing. Assertion is the process of making sure some condition is met. Most of the times the condition is a kind of check for the result of the tested unit. For example an array being empty, of a variable being filled with the proper value. Check this example, let's write a simple calculator class. This class has two methods: add and multiply. add method simply adds two integers and returns the result, but the multiply method uses the add method for multiplication.


public class Calculator {

    public int add(int a, int b) {
        return a + b;
    }

    public int multiply(int a, int b) {
        int result = 0;
        for (int i = 0; i < b; i++) {
            result += add(result,a);
        }
        return result;
    }
}

Enter fullscreen mode Exit fullscreen mode

For the add method my unit test would be like this :

@Test
public void testAdd() {
    int a = ThreadLocalRandom.current().nextInt();
    int b = ThreadLocalRandom.current().nextInt();
    int result = calculator.add(a, b);

    Assertions.assertEquals(a + b, result);
}
Enter fullscreen mode Exit fullscreen mode

For any two given integers, the result of add method should be equal to adding them together.
My unit test for multiply method would be like this:

    @Test
    public void testMultiply() {
        int a = ThreadLocalRandom.current().nextInt();
        int b = ThreadLocalRandom.current().nextInt();

        int multiplicationResult = calculator.multiply(a, b);

        Assertions.assertEquals(a * b, multiplicationResult);
    }
Enter fullscreen mode Exit fullscreen mode

It works, but there's something to note. We know that the multiply method heavily relies on the add method. If add is not working, there's no point in testing the multiply. For our example, it would not hurt much but in real-world problems, it may affect test time and resources heavily. What can we do? We can use Assumption.

@Test
public void testMultiply() {
    int a = ThreadLocalRandom.current().nextInt();
    int b = ThreadLocalRandom.current().nextInt();
    int additionResult = calculator.add(a, b);

    Assumptions.assumeTrue(a + b == additionResult);

    int multiplicationResult = calculator.multiply(a, b);

    Assertions.assertEquals(a * b, multiplicationResult);
}
Enter fullscreen mode Exit fullscreen mode

When assuming, you check the prerequisites of the test, if they are not available or do not have the expected value, there's no point in continuing with the test. In the above example, we first make sure that the add method is working properly.

Why not just assert them? The difference is if the assertion fails the test will fail but if the assumption fails the test will be ignored. Although in many tests they are asserted, that's not the way it should be. We do not want to test the functionalities of other methods, but we want to be sure that they are working properly.

If the tests are well written for all the parts of code, the part which makes the assumption fail would have proper tests that would fail.

For example, if our add method is not working properly, the testAdd would fail and the testMultiply would be ignored.

Discussion (2)

pic
Editor guide
Collapse
hbekkouche profile image
Hocine BEKKOUCHE

Very nice!.
but the 7th line i think is "Assumptions.assumeTrue(a + b == additionResult);"

Collapse
amaralani profile image
Amir Maralani Author

Thanks, yes you are right. Fixed!