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.

I have found that there are only 3 ways to unit test (mock/stub) dependencies that are static in C#.NET:

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.)

share|improve this question
1  
You can't call static methods in C#? Thats, wow. –  TheLQ Sep 21 '10 at 1:20
2  
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. –  acidzombie24 Sep 21 '10 at 2:44
9  
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. –  mlk Nov 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. –  user29776 Aug 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 Naylor Feb 1 '12 at 12:39

8 Answers 8

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.

share|improve this answer
17  
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. –  Vaccano Sep 21 '10 at 15:51
10  
@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 Harvey Sep 21 '10 at 18:41
10  
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. –  Vaccano Sep 21 '10 at 19:53
8  
@Vaccano: A static method that has outputs or random exceptions has side-effects. –  Tikhon Jelvis Dec 11 '11 at 3:55
1  
@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. –  NickC Aug 16 '12 at 23:04

Check this out: "Static Methods are Death to Testability". Short summary of the argument:

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.

share|improve this answer
13  
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 Harvey Sep 21 '10 at 14:53
3  
@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" –  Vaccano Sep 21 '10 at 15:48
4  
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 Diplo Sep 21 '10 at 16:10
2  
@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 Evers Nov 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 Reppen May 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.

share|improve this answer
2  
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. –  Vaccano Sep 21 '10 at 15:54
1  
Well, if your code is at the production level/quality of the .NET Framework then sure, go ahead. But the whole point of unit testing is the test the unit, in isolation. If you are also calling methods in other units (be they static or otherwise) then you are now testing your unit plus its dependencies. I am not saying it is not a useful test, but not a "unit test" by most definitions. (Because you are now testing your unit-under-test and the unit that has the static method). –  Vaccano Sep 21 '10 at 16:23
5  
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. –  cHao Sep 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 Diplo Sep 21 '10 at 19:06
2  
@Dan: For reference, 20 squared is 400. :) –  cHao Sep 21 '10 at 19:10

If the real question here is "How do I test this code?":

public class MyClass
{
   public void MethodToTest()
   {
       //... do something
       MyStaticClass.StaticMethod();
       //...more
   }
}

Then, just refactor the code and inject as usual the call to the static class like this:

public class MyClass
{
   private readonly IExecutor _externalExecutor;
   public MyClass(_IExecutor executor)
   {
       _exeternalExecutor = executor;
   }

   public void MethodToTest()
   {
       //... do something
       _exetrnalExecutor.DoWork();
       //...more
   }
}

public class MyStaticClassExecutor : IExecutor
{
    public void DoWork()
    {
        MyStaticClass.StaticMethod();
    }
}
share|improve this answer
3  
Fortunately we also have questions regarding code readability and KISS on SO too :) –  gbjbaanb Nov 15 '11 at 18:42
    
would a delegate not be easier and do the same thing? –  jk. Nov 29 '12 at 17:56
    
@jk could be, but its hard to use IoC container then. –  Sunny Nov 29 '12 at 21:11

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.

share|improve this answer

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".

share|improve this answer
2  
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 Pechtel Nov 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. –  g1ga Nov 30 '12 at 10:30
    
Not relevant to the question. –  Igby Largeman Mar 12 at 22:28
  1. 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
  2. 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.
  3. If I want to mock it, then I think it's generally the practice that it's declared on an interface.
  4. If it's declared on an interface then R# won't suggest you make it static.
  5. If it's declared virtual, then R# won't suggest you make it static either.
  6. 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... ;)

share|improve this answer
    
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. –  Vaccano Sep 21 '10 at 15:56
1  
No you cannot declare static on an interface. It would be meaningless. –  MIA Sep 21 '10 at 17:24

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.

share|improve this answer
    
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. –  Vaccano Sep 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 Pechtel Nov 30 '12 at 3:25

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.