There's no two ways about it. ReSharper's suggestions and several useful features of C# would not be used as often if you were writing isolated atomic unit tests for all your code.
For instance, if you have a static method and you need to stub it out, you can't unless you use a profile based isolation framework. A call-compatible workaround is to change the top of the method to use lambda notation. For example:
BEFORE:
public static DBConnection ConnectToDB( string dbName, string connectionInfo ) {
}
AFTER:
public static Func<string, string, DBConnection> ConnectToDB (dbName, connectionInfo ) {
};
The two are call-compatible. Callers don't have to change. The body of the function remains the same.
Then in your Unit-Test code, you can stub this call like so (assuming it's in a class called Database) :
Database.ConnectToDB = (dbName, connectionInfo) => { return null|whatever; }
Be careful to replace it with the original value after you're done. You can do that via a try/finally or, in your unit-test clean up, the one that gets called after every test, write code such as this:
[TestCleanup]
public void Cleanup()
{
typeof(Database).TypeInitializer.Invoke(null, null);
}
which will re-invoke the static initializer of your class.
Lambda Funcs are not as rich in support as regular static methods, so this approach has the following undesirable side-effects:
- If the static method was an extension method, you have to change it to a non-extension method first. Resharper can do this for you automatically.
- If any of the data types of the static methods are an embedded-interop assembly, such as for Office, you have to wrap the method, wrap the type or change it to type 'object'.
- You can no longer use Resharper's change-signature refactoring tool.
But let's say you avoid statics altogether, and you convert this to an instance method. It's still not mockable unless the method is either virtual or implemented as part of an interface.
So in reality, anyone who suggests the remedy to stubbing static methods is to make them instance methods, they would also be against instance methods that are not virtual or part of an interface.
So why does C# have static methods?
Why does it allow for non-virtual instance methods?
If you use either of these "Features", then you simply cannot create isolated methods.
So when do you use them?
Use them for any code that you don't expect anyone to ever want to stub out. Some examples:
the Format() method of the String class
the WriteLine() method of the Console class
the Cosh() method of the Math class
And one more thing.. Most people won't care about this, but if you can about the performance of an indirect call, that's another reason to avoid instance methods. There are cases when it's a performance hit. That's why non-virtual methods exist in the first place.