Given that two of these are not free and one has not hit release 1.0, mocking static stuff is not too easy.

Does that make static methods and such "evil" (in the unit testing sense)? And if so, why does resharper want me to make anything that can be static, static? (Assuming resharper is not also "evil".)

Clarification:
I am talking about the scenario when you want to unit test a method and that method calls a static method in a different unit/class. By most definitions of unit testing, if you just let the method under test call the static method in the other unit/class then you are not unit testing, you are integration testing. (Useful, but not a unit test.)

TheLQ: You can. I believe he is talking about not being able to test static methods because much of the time it touches static variables. Thus changing the state after and between test.
–
acidzombie24Sep 21 '10 at 2:44

13

Personally I think you are taking definition of "unit" too far. "Unit" should be "smallest unit that makes sense to test in isolation". That may be a method, it may be more than that. If the static method has no state and well tested then having a second unit test call it is (IMO) not an issue.
–
mlkNov 10 '10 at 11:46

7

"Personally I think you are taking definition of "unit" too far." No, its just that he's going with standard usage and you're making up your own definition.
–
user29776Aug 15 '11 at 14:26

3

"why does resharper want me to make anything that can be static, static?" Resharper doesn't want you to do anything. It is merely making you aware that the modification is possible and maybe desirable from a code analysis POV. Resharper is not a replacement for your own judgement!
–
Adam NaylorFeb 1 '12 at 12:39

10 Answers
10

Looking at the other answers here, I think there might be some confusion between static methods that hold static state or cause side-effects (which sounds to me like a really bad idea), and static methods that merely return a value.

Static methods which hold no state and cause no side effects should be easily unit testable. In fact, I consider such methods a "poor-man's" form of functional programming; you hand the method an object or value, and it returns an object or value. Nothing more. I don't see how such methods would negatively affect unit testing at all.

The static method is unit testable, but what about the methods that call the static method? If the callers are in another class then they have a dependency that needs to be decoupled to do a unit test.
–
VaccanoSep 21 '10 at 15:51

12

@Vaccano: But if you write static methods that do not hold state and have no side effects, they are more or less functionally equivalent to a stub anyway.
–
Robert HarveySep 21 '10 at 18:41

11

Simple ones maybe. But more complex ones can start throwing exceptions and having outputs that are not expected (and should be caught in the unit test for the static method, not in the unit test for the caller of the static method), or at least that is what I have been lead to believe in the literature I have read.
–
VaccanoSep 21 '10 at 19:53

11

@Vaccano: A static method that has outputs or random exceptions has side-effects.
–
Tikhon JelvisDec 11 '11 at 3:55

4

@TikhonJelvis Robert was talking about outputs; and "random" exceptions shouldn't be a side effect, they are essentially a form of output. The point is, whenever you test a method that calls the static method, you are wrapping that method and all permutations of its potential output, and cannot test your method in isolation.
–
NickCAug 16 '12 at 23:04

To unit test you need to take a small piece of your code, rewire its dependencies and test it in isolation. This is hard with static methods, not only in the case they access global state but even if they just call other static methods.

I don't keep global state or cause side-effects in my static methods, so this argument seems irrelevant to me. The article you linked makes a slippery slope argument that has no basis if static methods are confined to simple procedural code, acting in a "generic" way (like math functions).
–
Robert HarveySep 21 '10 at 14:53

4

@Robert Harvey - how do you unit test a method that uses a static method from another class (ie it has a dependency on a static method). If you just let it call it then you are not "unit testing" you are "integration testing"
–
VaccanoSep 21 '10 at 15:48

5

Don't just read the blog article, read the many comments that disagree with it. A blog is just an opinion, not a fact.
–
Dan DiploSep 21 '10 at 16:10

3

@Vaccano: A static method with no side-effects or external state is functionally equivalent to a value. Knowing that, it's no different than unit testing a method that creates an integer. This is one of the key insights that functional programming gives us.
–
Steve EversNov 29 '12 at 17:59

1

Barring embedded systems work or an app whose bugs have potential to create international incidents, IMO, when "testability" drives architecture, you had it twisted before you adopted test-every-last-corner-methodologies in the first place. Also I'm tired of XP's version of everything dominating every conversation. XP is not an authority, it is an industry. Here's the original, sensible definition of unit testing: python.net/crew/tbryan/UnitTestTalk/slide2.html
–
Erik ReppenMay 21 '13 at 20:35

You seem to be confusing static data and static methods. Resharper, if I remember correctly, recommends making private methods within a class static if they can be made so - I believe this yields a small performance benefit. It doesn't recommend making "anything that can be" static!

There is nothing wrong with static methods and they are easy to test (so long as they don't change any static data). For instance, think of a Maths library, which is good candidate for a static class with static methods. If you have a (contrived) method like this:

public static long Square(int x)
{
return x * x;
}

then this is eminently testable and has no side effects. You just check that when you pass in, say, 20 you get back 400. No problem.

What happens when you have another class that calls this static method? Seems simple in this case, but it is a dependency that cannot be isolated except with one of the three tools listed above. If you do not isolate it then you are not "unit testing" you are "integration testing" (because you are testing how well your different units "integrate" together.
–
VaccanoSep 21 '10 at 15:54

1

Nothing happens. Why would it? The .NET framework is full of static methods. Are you saying you can't use these in any methods you want to unit test, either?
–
Dan DiploSep 21 '10 at 16:01

6

Presumably you (or others) have already tested the static method and shown that it works (at least as expected) before writing too much more code around it. If something breaks in the part you test next, that's where you should look first, not in the stuff you've already tested.
–
cHaoSep 21 '10 at 19:03

3

@Vaccano So how do Microsoft test the .NET Framework, then, eh? Many of the classes in the Framework reference static methods in other classes (such as System.Math) not to mention the abundance of static factory methods etc. Plus you'd never be able use any extension methods etc. The fact is, simple functions like this are fundamental to modern languages. You can test these in isolation (since they will generally be deterministic) and then use them in your classes without worry. It is not a problem!
–
Dan DiploSep 21 '10 at 19:06

Statics aren't necessarily evil, but they can limit your options when it comes to unit-testing with fakes/mocks/stubs.

There are two general approaches to mocking.

The first one (traditional - implemented by RhinoMocks, Moq, NMock2; manual mocks and stubs are in this camp, too) relies on test seams and dependency injection. Suppose you're unit-testing some static code and it has dependencies. What happens often in the code designed this way is that statics create their own dependencies, inverting dependency inversion. You soon discover that you can't inject mocked interfaces into code under test that is designed this way.

The second one (mock anything - implemented by TypeMock, JustMock and Moles) relies on .NET's Profiling API. It can intercept any of your CIL instructions and replace a chunk of your code with a fake. This allows TypeMock and other products in this camp to mock anything: statics, sealed classes, private methods - things not designed to be testable.

There's an ongoing debate between two schools of thought. One says, follow SOLID principles and design for testability (that often includes going easy on statics). The other one says, buy TypeMock and don't worry.

I see that after long time no one has yet stated a really simple fact. If resharper tells me that I can make a method static, it means a huge thing to me, I can hear his voice tell me: "hey, you, these pieces of logic are not current class's RESPONSIBILITY to handle, so it should stay out in some helper class or something".

I disagree. Most of the time when Resharper says I can make something static it's a little bit of code that was common to two or more methods in the class and thus I extracted it out to it's own procedure. Moving that to a helper would be meaningless complexity.
–
Loren PechtelNov 30 '12 at 3:21

2

I can see your point only if the domain is very simple and it is not suitable for future modification. Differently, what you call "meaningless complexity" it's good and human-readable design to me. Having an helper class with simple and clear reason to exists is in some way the "mantra" of SoC and Single Responsibility principles. In addition, considering that this new class becomes a dependency for the main one, it has to expose some public members, and as a natural consequence it becomes testable in isolation and easy to mock when acts as a dependency.
–
g1gaNov 30 '12 at 10:30

I believe it's partly because static methods are "faster" to call than instance methods. (In quotes because this smells of micro optimization) see http://dotnetperls.com/static-method

It's telling you that it doesn't need state, therefore could be called from anywhere, removing the instatiation overhead if that's the only thing someone needs.

If I want to mock it, then I think it's generally the practice that it's declared on an interface.

If it's declared on an interface then R# won't suggest you make it static.

If it's declared virtual, then R# won't suggest you make it static either.

Holding state (fields) statically is something that should always be considered carefully. Static state and threads mix like lithium and water.

R# isn't the only tool that will make this suggestion. FxCop/MS Code Analysis will also do the same.

I would generally say that if the method is static, generally it should be testable as is as well. That brings some design consideration and probably more discussion than I have in my fingers right now, so patiently awaiting the down votes and comments... ;)

Can you declare a static method/object on an interface? (I do not think so). Ether way, I am referring to when your static method is called by the method under test. If the caller is in a different unit then the static method needs to be isolated. This is very hard to do with out one of the three tools listed above.
–
VaccanoSep 21 '10 at 15:56

1

No you cannot declare static on an interface. It would be meaningless.
–
MIASep 21 '10 at 17:24

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 ambda notation. For example:

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:

Lambda Funcs are not as rich in support as regular static methods, so this approach has the following undesirable side-effects:
1. 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.
2. 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'.
3. 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.

The simple truth rarely acknowledged is that if a class contains a compiler-visible dependency on another class, it cannot be tested in isolation from that class. You can fake up something that looks like a test, and will appear on a report as if it was a test.

But it will not have the key defining properties of a test; failing when things are wrong, passing when they are right.

This applies to any static calls, constructor calls, and any reference to methods or fields not inherited from a base class or interface. If the class name appears in the code, it is a compiler-visible dependency, and you can't validly test without it. Any smaller chunk simply is not a valid testable unit. Any attempt to treat it as if it were will have results no more meaningful than writing a little utility to emit the XML used by your test framework to say 'test passed'.

Given that, there are three options:

define unit testing to be testing of the unit composed of a class and it's hard-coded dependencies. This works, providing you avoid circular dependencies.

never create compile-time dependencies between classes you are responsible for testing. This works, providing you don't mind the resulting code style.

don't unit test, integration test instead. Which works, providing it doesn't conflict with something else you need to use the term integration testing for.

I believe that Resharper is giving you guidence and apply the coding guidelines it has been setup with. When I have used Resharper and it has told me that a method should be static it is bound to be on a private method that does not act on any instance variables.

Now as for testablity this scenario shouldn't be an issue as you shouldn't test private methods anyway.

As for the testability of static methods that are public then unit testing does become hard when static methods touch static state. Personally I would keep this to a minimum and use static methods as pure functions as much as possible where any dependencies are passed into the method which can be controlled via a test fixture. However this is a design decision.

I am referring to when you have a method under test (not static) that calls a static method in another class. That dependency can only be isolated with one the three tools listed above. If you do not isolate it then you are integration testing, not unit testing.
–
VaccanoSep 21 '10 at 15:52

Accessing instance variables inherently means it can't be static. The only state a static method can possibly have is class variables and the only reason that should happen is if you're dealing with a singleton and thus don't have a choice.
–
Loren PechtelNov 30 '12 at 3:25