Unit testing a method that calls another method

Solution 1:

This is a classic state-based test vs. behavior-based test scenario.

In this ridiculously simple example testing the output is fine. At some point though, you'll run into tests where inspecting the state after execution is complicated. Instead you want to check the behavior (e.g. verify that changeit was called with a specific value).

At that point you probably should look into a mock object framework like Rhino.Mocks (.Net) or Mockito (Java) and start writing more interface based code.

Solution 2:

You have a number of options. Which one is best depends on details that aren't clear from your question.

  • test modify just as if it were an unrelated method. Advantage: it might at some point become one.
  • just test that you got the if-statement right. That is, just test enough that the tests force you to write the implementation you need (where calling replaceit and changeit is just the simplest implementation that could possibly work. If your are practicing TDD, this should come naturally to you. Advantage: high test coverage without much duplicated effort.
  • Subclass and Override Method (this is a dependency breaking technique from the book "Working Effectively With Legacy Code"): Test the method on a subclass that you introduce solely for testing purposes, which overrides replaceit and changeit with canned answers or so that they set sensing variables (variables that indicate whether the method has been called with the right value(s)). Advantage: might possibly simplify your tests (or not), sometimes even just make testing possible.
  • Extract a new class for the replaceit and changeit methods, including an interface for that class. Stub or Mock that interface when testing modify. Advantage: might both make your design more testable and better decoupled/reusable in general (or not).

Solution 3:

If you have already tested replaceit() and changeit() independently, then the only thing you have left to test is the if condition. Test modify() with a few values to make sure it calls the right function under the right conditions (those conditions being null and Strings of length 4, 5, and 6 for the example code you gave).