Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Let's say you have a static method that looks something like this:

public static bool Foo()
{ 
    var bar = new Bar();
    //do some stuff here
}

This method as it stands can be a real headache to unit test.

What is the best practice to refactor this so that it can be testable, without turning it into an instance method or changing the method signature?

share|improve this question
2  
I've deleted my post as it was invalid for your updated scenario. You may find this valuable: googletesting.blogspot.com/2008/12/… –  ysolik Oct 15 '10 at 19:27
1  
As an aside, this probably belongs on stackoverflow –  Chris Knight Oct 15 '10 at 19:42
    
@Chris: agree about StackOverflow or perhaps on that now-defunct "Developer Testing: Unit-testing and more..." site! –  azheglov Oct 15 '10 at 19:58
    
Developer Testing has been canned, which is why I put the question here. I didn't think it belonged on SO because I thought it would be too subjective (hence best practice) –  Joseph Oct 18 '10 at 15:31
add comment

2 Answers

up vote 8 down vote accepted

It really depends on what Bar is. If it's something simple then your Foo method is already testable, you just need to specify your expectations and invoke it statically, e.g.:

Assert.IsTrue( FooContainer.Foo() );

But if Bar encapsulates, say, your database access layer, then you can't test Foo without a real database, which is why (thanks @ysolik), static methods are death to testability. Or, in the words of Michael Feathers, "don't hide a TUF in a TUC" (TUF stands for a test-unfriendly feature, TUC stands for a test-unfriendly construct). If Bar is indeed test-unfriendly, then sorry, it doesn't work well without making Foo an instance method. You would need to redesign your code first:

public class FooContainer {
    public bool Foo() {
        var bar = new Bar();
        //...
    }
}

When Foo is no longer static, you can invoke it on an instance of FooContainer:

var container = new FooContainer();
Assert.IsTrue( container.Foo() );

The next step is to extract an interface from Bar (let's call it IBar) and inject it into FooContainer:

public class FooContainer {
    private readonly IBar m_bar;
    public FooContainer( IBar bar ) { m_bar = bar; }
    public bool Foo() {
        // don't create another Bar, use m_bar
    }
}

Now you can mock/stub IBar with your favourite isolation framework and test your FooContainer code in isolation from its dependencies.

share|improve this answer
add comment

What is the point of Foo? What does it do? What is a Bar?

It seems from your question that Bar is a class that introduces side effects, or Bar is a resource.

Either way, in both circumstances, without changing the method signature, you're hooped without going into the ill-fated world of pre-processor directives (#if test var bar = FakeBar(); // = bad).

If Bar is a class that introduces side effects: without injecting that dependency or returning whatever it affects, you're in trouble.

If it's a resource (Stream, DBConnection, etc.) then the only realistic options I can see is to:

  1. Extract out an interface and take an IBar as a parameter like @azheglov says

  2. Create a fake/stub that inherits from Bar and pass that as a parameter

What it boils down to is that you're likely going to have to change the method signature, reduce side-effects and not create hidden dependencies if you want to make it easier to test.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.