views:

178

answers:

4

So I have a class that looks something like the following:

public class MyClass
{

    DatabaseDependency _depend;

    public MyClass(DatabaseDependency depend)
    {
        _depend = depend;
    }

    public string DoSomething(DBParameter database)
    {
        var result = _depend.GetResults(database, ...);
        string response = String.Empty;        

        // some logic to process the result 

        return response;
    }

}

Where DBParameter is a simple value class which contains properties like Server, DBName, DBType, etc.

Now, I want to add an overload to DoSomething so that it accepts a connection string instead of the DBParameter parameter (assume that DatabaseDependency already has a GetResults overload which accepts a connection string).

My question: I have several unit tests which describe the various logical paths used to process result from DatabaseDependency.GetResults. When I add the overload to DoSomething, I would essentially refactor the code so that this logic is reused by both overloads (i.e. probably move it to a private method). What is the right way to go about unit testing this? Do I need to have just as many unit tests to verify all logical paths for the new overload I am adding?

+5  A: 

If you're confident that your overloaded method taking a string just converts to a connection object and then delegates to the original, you should add one more test method.

However this breaks down if you refactor the underlying overloaded methods such that no delegation takes place. In this scenario I'd feel more confident replicating all the tests for both methods.

I think the first route is the most pragmatic. However it's a good idea to run code coverage analysis once in a while, and that will indicate at a later time if more tests are required.

Brian Agnew
+1  A: 

Yes, refactor the common processing to a private method - I assume that you would do this anyway irrespective of test considerations, duplicate code is bad. It's interesting how thinking about testing leads us to do the right thing.

Then you have a couple of simple tests for each overlaoded initiation path.

djna
+3  A: 

If your code stays the way it currently looks, then yes: you will need to unit test that method as well, essentially duplicating your test effort.

However, if it makes sense to implement the functionality so that one method simply calls the other, you could make that other method virtual. That would allow you to create a test-specific subclass where you simply verify that the virtual method is being invoked by the other method with the correct values.

Once that is verified by one or more unit tests, you don't need to test that method any further, because now you have proven that the method calls the other method correctly, and you can concentrate your testing efforts on that method.

Mark Seemann
A: 

Depends if you are doing black-box or white-box testing and also if you're application is using both versions of the method.

If you're assuming that you're just testing implementation, then simply testing the 'main' version would be OK. If you're thinking along the lines of a test writer that only knows about the presented API (javadocs or similar) then you need to test based only on the API, which implies testing both methods completely.

If you're application is using only one method, then deprecate the other and create a version conditional test that fails when the deprecated method still exists at some pre-determined version. IE: enforce that the deprecated method is removed at some point.

ptomli