Advice needed for refactoring legacy code

Complexity :

I'm working a legacy code base and I would to use TDD to add new features to the code that I'm currently changing.

Please note that the current code base does NOT have any UT'S.

I have a Calculator class with the following implementation:

public final class Calculator extends CalculatorBase {
    public Calculator(Document document) throws Exception {
        super(document);
    }

    public int Multiply(int source, int factor) {
        return source * factor;
    }
}

This class inherits from the following base class:

public class CalculatorBase {
    public CalculatorBase(Document document) throws Exception {
        throw new Exception("UNAVAILABLE IN UT CONTEXT.");
    }
}

NOTE: The constructor does actually a lot of things, which I would like not to do in UT's. For simplicity, I've made the constructor throw an exception.

Now I want to add an 'Add' function to the Calculator class. This function looks like:

public int Add(int left, int right) {
    return left + right;
}

A UT for this particular piece of code should be very straightforward.

@Test
@DisplayName("Ensure that adding numbers DOES work correctly.")
void addition() throws Exception {
    // ARRANGE.
    Calculator calculator = new Calculator(null);

    // ACT.
    int result = calculator.Add(1, 1);

    // ASSERT.
    Assertions.assertEquals(2, result);
}

Since the constructor of the CalculatorBase base does throw an exception this unit test will NEVER pass.

The tricky part to make this testable is that the CalculatorBase class is auto generated by a tool, thus the source code of that class cannot be modified.

What (baby) steps should I take to make ensure that the Add method on the Calculator class can be tested? The goal is to make the whole project testable, and even get rid of the auto generated stuff, but I would like to use TDD wherever possible in order to refactor the code gradually.

One could argue that I can make the Add method static since it doesn't use any dependencies of the Calculator class, but the code is just quickly added together. The Add function is, in the actual scenario, something else which does consume the state of the Calculator class.

borjab :

You can:

  1. Create the new method as static
  2. Create a temporal alternative constructor commented as "Only for testing"
  3. Refactor the class to remove the dependency
  4. Suppress it with PowerMock

But the safest way to do it is to create an scaffold test. This build the class even if the constructor has dependencies. You may need to break the encapslation with setters just for testing. Once the class is really well tested you may refactor the class, add better tests and finally remove the dirty scaffold test. Depending on the complexity of the class this may be appropiate or an overkill.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=388989&siteId=1