Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Practices for refactoring unit tested code

Suppose I have a function like this:

public void AddEntry(Entry entry)
{
    if (entry.Size < 0)
        throw new ArgumentException("Entry size must be greater than zero");
    DB.Entries.Add(entry);
}

And a corresponding unit test:

[TestMethod]
[ExpectedException(typeof(ArgumentException), "Entry size must be greater than zero")]
public void AddEntry_TermSizeLessThanZero_ThrowException()
{
    Entry e = new Entry(-5);

    AddEntry(e);
}

And then I refactor the validation code out:

public void AddEntry(Entry entry)
{
    Validate(entry);
    DB.Entries.Add(entry);
}

public void Validate(Entry entry)
{
    if (entry.Size < 0)
        throw new ArgumentException("Entry size must be greater than zero");
}

The unit test no longer describes the validation code.

What's the best thing to do in this case? Do I just leave Validate() to be tested through AddEntry?

Edit: to clarify, supposing I had a reason to make the refractored code public (a bit contrived in this situation), would I want to duplicate the test code to be thorough?

like image 319
Rei Miyasaka Avatar asked Dec 29 '22 10:12

Rei Miyasaka


1 Answers

Since you made the Validate() method a public member of your object (for whatever reason) you should certainly add a seperate test for it. The test for AddEntry should remain in place.

A unit test should only test the interface of a unit and shall not assume any implementation details. So in this case you should leave your test for AddEntry in place the way it is, because it describes the behavior of your interface. But you should not assume or test that AddEntry() calls Validate().

like image 126
Johannes Rudolph Avatar answered Jan 14 '23 02:01

Johannes Rudolph