Nate Major
Nate Major

Reputation: 77

If my unit test doesn't test logic, am I really accomplishing anything substantial?

I'm new to unit testing, and I'm using NSubstitute for mocking. I have read a few articles on the high level purpose of unit testing, and a lot of the rationales are pretty agreeable. However, I can't seem to understand how my test is worthwhile if it isn't testing any logic in a concrete class.

Using the example from NSubstitute's documentation (http://nsubstitute.github.io/help/getting-started/), let's assume a basic calculator interface:

    public interface ICalculator
    {
        int Add(int a, int b);
        string Mode { get; set; }
        event EventHandler PoweringUp;
    }

We'll use NSubstitute to substitute an instance, specify a return, and use an Assert for testing:

    calculator = Substitute.For<ICalculator>();
    calculator.Add(1, 2).Returns(3);
    Assert.That(calculator.Add(1, 2), Is.EqualTo(3));

Because we've specified that 3 will always be returned when 1 and 2 are passed to the Add method, how does this help us test potentially faulty logic that exists inside a concrete class that implements the ICalculator interface? And if it doesn't, why is this test worthwhile at all?

Thanks!

Upvotes: 1

Views: 121

Answers (2)

Peter
Peter

Reputation: 27944

Your test is not worthwhile because you are not testing logic. At this point you are only testing if your testing framework is correct. To make your test worthwhile you should test the logic depending on calculator.Add and let the add return 3. Make a separate test for you add function. By isolating your code into units which can be validated separately. If you are testing the code depending on the Add function you do not want that code to fail because your Add implementation is not correct. It should assume your Add function is correct because it is tested separately.

Upvotes: 1

Mureinik
Mureinik

Reputation: 311948

Unit tests, as you noted, are (mainly) meant to test logic. In the example you've given, you're testing that a mocked object returns the expected mocked result - so unless you're developing itself and want to test that it successfully substitutes an object, you're right, this is pretty meaningless.

Mocking is usually used to check the logic of a collaborator class. For example, consider this (stupid) method that takes some action if two numbers add up to three:

public boolean AreTheyThree(int a, int b, ICalculator calc)
{
    return calc.Add(a, b) == 3;
}

Now, if you'd like to test a method like this, it makes sense to mock (substitute) the ICalculator you're using, since you don't want to rely on specific implementation details, or have the test for your logic fail if a regression is introduced to a specific ICalculator implementation:

calculator = Substitute.For<ICalculator>();
calculator.Add(1, 2).Returns(3);
Assert.That(myObject.AryTheyThree(1, 2, calculator), Is.EqualTo(true));

Upvotes: 2

Related Questions