Why Static methods are bad for UnitTest?

The whole idea behind unit testing is to isolate the system under test (SUT) so you can control all the variables and be able to simulate different scenarios to see how your system behaves.  The isolation process usually involves initializing a fake/stub instance and injecting it into the SUT.  However with statics, there is no instance to initialize so there is nothing to mock.  Your class is tightly bound to that static method and there is no way to free it and isolate the system without doing extra work or using specialized mocking frameworks.  (On a side note, I don’t think using these specialized mocking framework is a good idea either, because they promote bad software design.  If you follow SOLID design principles then unit testable architecture comes naturally).

Lets look at an example where the method I want to test calls out to some static method and see what problems it creates.

applydiscountPNG

Lets assume that we want to verify that the 15% discount is being applied correctly.  We need a way for the static Validate() method to return true in order to get to the discount calculation logic.  You could extract the call to the static method into a protected virtual method in order to introduce seam, which we can use during testing, but that’s writing more code which we are trying to avoid because chances are most developers wont even bother.  You could go into the static Validate() method and try to figure out what constitutes a valid accountId.

static

In this case it’s not that complicated either – I’ll just pass in 5004 as the accountId in my test, so what’s wrong.  Well, what you have done is made your test very brittle, because the ApplyDiscount() test could fail if anything changes in the static Validate() method.  Imagine the static Validate() method internally called some other static method, now you are just going deeper and deeper into the rabbit hole and you might never get out.  Also there is no way to write unit test for static methods.  So please stop writing functional utility methods and embrace object oriented programming, it’s about time don’t you think!

Random C# and CLR thoughts

– Overflow checking is Off:

CLR has different instructions based on whether to perform overflow checking: add, subtract, multiply and its corresponding add.ovf, subtract.ovf and multiply.ovf.  To improve performance it does not check for overflow when performing calculations on primitive types (except System.Decimal, which we will get to later).  So, if you do not want overflows to happen in your system then wrap your statement in C# checked operator which will force the CLR to use the xxx.ovf instruction and throw OverflowException if it finds one.  Now going back to the Decimal data type, the checked/unchecked operator has no effect on it and is simply ignored (Decimal always throw an OverflowException if the operation can’t be performed safely).  On other note, Decimal is not considered a primitve data type by the CLR, which means that manipulating it will be slower than primitive values since it does not have IL instructions built into it.

overflowPNG

 

– Implicit/explicit conversion operators – what..?

Simply put, these convert an object from one type to another type either implicitly or explicitly.  I prefer the ‘explicit’ operator and force the developer to make a conscious decision on what the heck they are doing (by applying the cast operator).  Example is as follows:

implicit_explicit

In either case (implicit/explicit) the compiler will always explicitly apply the cast operator, which we can see here

compiler casting

 

– Layout.Auto/Layout.Sequential attributes

The Auto attribute tells the CLR that it is ok to rearrange fields in memory and group them in certain ways to improve performance, whereas the Sequential attribute says not to mess with the programmer defined field order.  By default Layout.Auto is applied to Reference types and Layout.Sequential to Value types, because the value type field ordering might be important when dealing with unmanaged code.  However, if you know that your code won’t have to integrate with unmanaged code you can apply the Layout.Auto attribute to your value types in order to allow the CLR to optimize your code.

LayoutKind

 

– C# is and as operators

They are different from an explicit cast operator in that both of these operators does not throw an exception. is returns boolean and as performs the cast if applicable or returns null, blah, blah… stuff we all know.  However, the second code snippet is more performant no matter how small, so pay attention when you code.

Inheritance_bad

inheritance_good

 

– More random thoughts

Value types will never throw NullReferenceException because a value type variable isn’t a pointer to some reference on the managed heap, it is actually allocated on the thread stack itself (no GC as well).

Value types derive from System.ValueType which derives from System.Object.

Enum types derive from System.Enum which derives from System.ValueType.

So, as they say – System.Object is the mother of all freak’n objects – enough said Smile