How should we test the following code

    void printIt(int a, int b) {
        if (a + b >= 0) {
            System.out.println("positive");
        } else
            System.out.println("negative");
    }

Short answer: we shouldn’t. It’s doing far too much. We should rewrite it before testing it.

Step 1: Count responsibilities

Decide how to refactor it

It is policy to Avoid Side Effects. In addition we have an ‘if statement’ and the policy states ‘Avoid if/switch statements except to create objects’. This if statement isn’t actually that bad (it’s not chaining together a load of business logic), but it’s worth experimenting with getting rid of it.

Suppose we refactored this as

    interface PrintIt {
        void println(String message);
    }

    enum Sign {
        Positive("positive"), Negative("negative");

        public final String name;

        public static Sign determine(int value) {
            return value >= 0 ? Positive : Negative;
        }

        Sign(String name) {
            this.name = name;
        }
    }

    final private PrintIt printer = //injected by dependency injection;

    void printIt(int a, int b) {
        printer.println(Sign.determine(a + b).name);
    }

Each part of the code is now trivial to test. The test for Sign.determine handle the responsibility of determining if positive or negative. We can test the names of Positive and Negative. The printit method just needs to assert that it passed the name of Sign.determine to the printer.

Alternative Refactoring

Another approach is

    private final Printwriter printer = // injected by depedency injection
    final static String positive = "positive"; 
    final static String negative = "negative"; 
    void printIt(int a, int b) {
        if (a + b >= 0) {
            printer.println(positive);
        } else
            printer.println(negative);
    }

This is a little better because we are avoiding singletons. It’s less good because the idea of ‘the sign’ of the sum of the two numbers hasn’t been extracted. If this is a common business thing (and it often is) it would be better as an enum.