views:

190

answers:

4

I have this method:

public bool CanExecute()

And after 70 commits, I added an extra parameter

public bool CanExecute(IStation target)

Now the problem is I have 7 unit tests covering this CanExecute methods testing various nulls/property combinations.

Adding this simple parameter required a fix of those 7 unit tests. The fix is simple but...

Is there a best practice and/or pattern to avoid this kind of hand-refactor required to update unit tests?

Suppose I know an extra parameter might be added in the near future, how'd I code the unit test to account for that? Is it just overkill or is there an idiom/pattern/something to follow?

EDIT: I could not simply add an overload because the IStation dependency is not optional. I was fixing a bug where an IStation instance was expected but none was available so it must be supplied via CanExecute... you see.

Refactoring tools seem to be the way to go. Thanks!

+9  A: 

Could you not keep both methods in the code? Unless it is mandatory for the IStation parameter to be non null then you could get away with it without changing any existing code.

Alternatively if the parameter has a sensible default (again, like null!), resharper can take care of changes like this very easily. To add a new parameter, right click the function name and select Change signature... From here you can add new parameters with sensible defaults. RS will update all the calls so you don't have to !

Jennifer
+1, resharper does this, there is no need to refactor by hand.
David Lay
+1, good tip to keep the overloaded method around if you want to avoid changing the calling code
orip
VS2005 can almost get you there with the Refactor > Promote Local Variable to Parameter right-click option. Make sure you have a local variable with an assignment on the same line. Probably not as good as RS, but it works in a pinch.
Pedro
+1  A: 

You do of course need to consider if you're duplicating too much functionality across your unit tests, but this may not always be the case.

Quite a few modern IDEs (resharper for C#) support "change method" refactoring which allows you to supply default values for new parameters. I find this refactoring functionality to be really rewarding to master.

krosenvold
+1  A: 

If you know that the method is likely to change yet again, I think the sensible thing to do is overload the method and add unit tests for the overloaded members, instead of changing old unit tests. If the stars align for you, you might even find that the overloaded methods call the original no-arg method, so you only have to write tests for the new parameters, and not repeat the original seven tests.

Bill the Lizard
Is it okay to make assumptions based on the (current) implementation details of the methods you test? My understanding is that changes to internal implementation details of a method (but which don't change the "interface" or behavioral guarantees of the method) shouldn't require unit test changes.
Reuben
You *should* only unit test public methods, but implementation changes can cause changes to the expected return value of a method, so sometimes tests have to change even when the API stays the same. So, essentially yes, you are testing the current implementation of your method.
Bill the Lizard
A: 

I'd keep both. Overload the method and add unit tests for the new overloaded methods to cover what you've just added.

Bryan Denny