Tuesday, March 25, 2014

Why is my code not covered by a Unit Test?

In this article, I am going to speak about a simple method that is not covered in code coverage even though the method is called by the parent method. This surprises many programmers at first instance.
A brief history of “yield” keyword in C# language:
As per MSDN, When you use the yield keyword in a statement, you indicate that the method, operator or get accessor in which it appears is an iterator.
“yield” returns one element at a time.
Iterator Pattern:
Added advantage with the “yield” keyword in your code is making you follow a design pattern by implicit. Yes. By using “yield” keyword you are following Iterator Pattern.
Iterator provides a way to access the elements inside an aggregate object.
Now coming to the main topic of why my method is not covered by Unit Test method.
To explain this I am going to create a class library and add two classes: Country.cs and Data.cs.
The class library name is “DataRepository” and the intention of the library is provide the Country names with Ids. To perform that we need to define the type for “Country” and another type that provides the methods to return the Country names and Ids.
Here is the type “Country”:
image

Here is the class for the provider methods: This class has a public method that is exposed to the clients and one private method that actually reads the data and returns the countries to the public method.
image
Now, let us add a test project and a unit test for the “Data” class public method. The intention of the test method is make sure that the public method of the class “Data” does not return null. This is a simple test.
image
Now execute the unit test and make sure that test is passed and then observe the code coverage details. I am using DOTCOVER (trial version) for code coverage. If you observe the overall Code coverage is 33% and the method “GetCountriesCore” was not covered. Try to put a break point and debug the unit test method, but still debugger will not step into the method “GetCountriesCore”.
image
Also because the type “Country” is called by the method “GetCountriesCore”, it is also not covered.
Now back to the question “Why is my code is not covered even though it is invoked?”
The answer lies in the implementation of the method. The method has “yield” keyword which makes the method to be an iterator and your enumerable method will only execute when you actually try to access the members. This is also called “Deferred Execution”. There is an interesting article in MSDN on the deferred execution: http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx
So, now change the unit test method to iterate through the members of the returned type of the method as below:
image
Now run the tests again and if we put a break point, you can step into the private method too. We should see all green now and coverage percentage should be 100%. Also if you observe, the code for class “Country” is now covered and overall coverage is good now.
image
Hope you find this article useful. Happy Coding!!!

No comments:

Post a Comment