Search code examples
unit-testingtestingintegration-testingassert

Can unit/integration tests have no assert? And what about this particular case?


Scenario: I have some integration tests. One of them tests a delete. So I've done:

@Test
@Order(6)
public void delete() {
    rfxCriteriRepository.delete(rfxCriteriEconomico.getIdrfxcriteri());
}

to simply test if the method throws no exception. Than, to be sure that the delete is successfull, I've added:

@Test
@Order(7)
public void getDelete() {
    RfxCriteri rfxCriteriEconomicoDb = rfxCriteriRepository.findByIdrfxcriteri(
        rfxCriteriEconomico.getIdrfxcriteri()
    );

    Assertions.assertNull(rfxCriteriEconomicoDb);
}

My idea is that the first test tests the code. If the code is well written, it should throw no exception, and the test pass. The second test tests that the delete effectively deleted the entry from the database. IMHO they are two separate tests.

Do you think every test must have an assert? Or do you think these two tests should be an unique test? Can someone point me to some guide about unit testing that says something about it?


Solution

  • Every test requires that the results are evaluated in some form. But, that can in some cases be implicit. For example, many test frameworks treat uncaught and unexpected exceptions that occur during the execution of a test as test failures. When you are using such a framework and you have a test where it is only important that no exception was raised, then you could write that test without any explicit assert statement - the framework performs the assertion for you.

    It is, however, not very common to have tests for which the only success criterion is that no exception was raised. But, there are situations when this makes sense: Take the classical example where a triangle is defined by passing the lengths a, b and c of the three sides. Then, one corner case is that the sum of two sides equals the third side, like a == b + c. Then, you could have three test cases to test the boundaries:

    1. One case where the sum of two side lengths is just above (by an epsilon) the length of the third side: a + epsilon == b + c - this would be a valid triangle in any case.
    2. One case where one side is longer (again by an epsilon) than the sum of the other two, for example a - epsilon == b + c. This should raise an exception since this is no valid triangle.
    3. Finally the situation where a == b + c.

    Assume that in your code the situation in case 3 shall produce a degenerate but valid triangle. Then it can make sense to have a test case that does nothing more than just create this triangle - to see that no exception is thrown. Remember that your tests can also be considered as documentation of your code: Such a test documents nicely that your code allows to create such triangles. The test case should in this case certainly be implemented and named such that the intent becomes clear, like, "constructing_aDegenerateTriangle_shallSucceedWithoutExceptionRaised".

    Now, coming to the second part of your question, whether in your specific situation a test without assertions makes sense. In this case I would also only consider the combined test mentioned by JBNizet as useful (which deletes and then checks that the entry was truly removed). You could have both tests individually - but the one testing for the assertion would be redundant, because the implicit assertion check of the test framework would be done anyway in both test cases.