We have talked a lot about what to test and cover. Let’s quickly discuss what not to cover. Achieving 100% coverage may be impossible or not even desirable. For example, the code snippet in listing 3.12 returns the full path of a specific directory. The code may throw a URISyntaxException, which we catch and wrap around a RuntimeException. (For the Java experts, we are converting a checked exception to an unchecked exception.)

Listing 3.12 A method that does not deserve full coverage

public static String resourceFolder(String path) {
  try {
    return Paths.get(ResourceUtils.class
      .getResource("/").toURI()).toString() + path;
  } catch (URISyntaxException e) {
    throw new RuntimeException(e);
  }
}

To achieve 100% line coverage, we would need to exercise the catch block. For that to happen, we would have to somehow force the toURI method to throw the exception. We could use mocks but I cannot see any advantage in doing that. It is more important to test what would happen to the rest of the system if resourceFolder threw a RuntimeException. That is much easier to do, as we have more control over the resourceFolder method than the Java toURI() method. Therefore, this piece of code it is not worth covering and shows why blindly aiming for 100% coverage makes no sense.

In Java, in particular, I tend not to write dedicated tests for equals and hashCode methods or straightforward getters and setters. These are tested implicitly by the tests that exercise the other methods that use them.

To close this discussion, I want to reinforce that, for me, all code should be covered until proven otherwise. I start from the idea that I should have 100% coverage. Then, if I see that a piece of code does not need to be covered, I make an exception. But be careful—experience shows that bugs tend to appear in areas you do not cover well.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *