Is it a bad practice to test the flow of logic by log statements?

Viewed 49

I have a logic that does something like this that I want to test out:

public void doSomething(int num) {
  var list = service.method1(num);
  if (!list.isEmpty()) {
    // Flow 1
    LOG.info("List exists for {}", num);
    doAnotherThing(num);
  } else {
    // Flow 2
    LOG.info("No list found for {}", num);
  }
}

public void doAnotherThing(int num) {
  Optional<Foo> optionalFoo = anotherService.get(num);
  optionalFoo.ifPresentOrElse(
      foo -> {
        if (!foo.type().equals("no")) {
          // Flow 3
          anotherService.filter(foo.getFilter());
        } else {
          // Flow 4
          LOG.info("Foo is type {} - skipping", foo.type());
        }
      },
      // Flow 5
      () -> LOG.info("No foo found for {} - skipping", num));
}

For each test that'll test out different flow, my first thought was to Mockito.verify() to see if they were called or not. So to test out Flow 1, I would verify that anotherService.get() was called inside doAnotherThing(). And to test out Flow 2, I would verify that anotherService.get() was never called. This would've been fine except for Flow 4 and Flow 5. They would both invoke anotherService.get() once but not anything else.

Because of that, I've created a class to capture logs in tests. This would check to see if certain logs were logged and I would be able to see by it which flow it landed on. But I wanted to ask: is this a bad practice? I would combine this with verify() so that on flows that can be reached by verify() will take that as higher precedence.

One downside to this would be that the tests would rely on the log messages being correct so it would be a bit unstable. To account for that issue, I thought about taking some of these log messages out as a protected static variable that the tests can also use so the message would remain the same between the methods and the respective tests. This way, only the flow would be tested.

If the answer is that it is a bad practice, I would appreciate any tips on how to test out Flow 4 and Flow 5.

1 Answers

Log statements are usually not part of the logic to test but just a tool for ops. They should be adjusted to optimize ops (not too much info, not too few), so that you can quickly find out if and where something went wrong, if something went wrong. The exact text, the log levels and the number of log statements should not be considered as something stable to rely your tests on. Otherwise it will make it harder to change the logging concept.

Related