One of the best practices to write good quality software is to create the Unit test along with the functionality you are creating and try to keep your code close to 100% coverage during project development.
This post will be lead by examples, since I think it is easier to conduct such a practical topic by examples.
Let’s see an example about how to re-factor a class to make feasible the test.First of all we will start a VS2012 console application and create a new class named A and a method of A that performs a Arithmetic calculus named Calculate().
Then creates a new class named B that uses Calculate method from A
To accomplish the behavior above, B needs and instance of A to access the Calculate method, so it creates a private property from A in B and then uses the public method Calculate from A in Calculus method.
In this case we can say that there is coupling between B and A that means that in order to B accomplish their behavior needs to create an instance of A and invokes a method of it.
Let’s create a unit test project and add coverage for A and B
Then on the test project add a reference to our dummySample1 project and create a new class ATest.cs for test A behavior.
Also we will create a BTest.cs class to test the B class behavior. Since B uses an instance of A to accomplish its task, the test will cover again the use of A, this is due to the high coupling that exists between A and B, also if A changes then B test will fail.
Unit test are intended to test isolated chunks of code so just for definition the following test is not a good test, it also reveals that the Class B should be decoupled from class A.
After creating this test lets change the behavior of Calculate method in A class. It was an addition and change it by product operation finally change the ATest class accordingly.
Running the test we realize now that ATest works but BTest fails, that was expected to fail because of the coupling.
Now we will refactor A and B in order to move dependencies outside B and see how the test works.
I’ve created an interface for A that is a contract that says A has a method Calculate that receives 2 integer parameters and returns and integer result.
Then A extends the interface and implements the IA Calculate method
After that we will update B class to use the Interface IA and also accepts by constructor the object A.
Now we can test B providing a fake behavior for A Calculate method, using a mocking library named Castle Moq, so we will be testing how B works without worrying what A class do. On the other hand if A class should change the way it perform its mathematical function B won’t be affected and the test will keep the same.
The aim to unit test is to keep track of code changes so having 100% coverage with good test cases, this means not just adding coverage but adding test cases the check exceptions and non envisioned behavior, will help to prevent that changes on the code that could affect other places will be put into evidence because some of the test that covers it usage will fail.
The code needs to be decoupled in that way it can be unit tested in small chunks and any error will be easy to find and fix.