In my previous post on Partial Mocks, I had made a note that the method which we intend to partially mock has to be a public virtual method. Immediately after publishing the post, I came across a post by Matt Roberts which demonstrated how to use InternalsVisibleTo attribute to expose protected methods to certain assemblies. In this post I’ll demonstrate how to use InternalsVisibleTo attribute to unit test internal methods.
What’s the problem with earlier approach?
If we look at the code from the previous post, we had to make the methods public to be able to mock them using Rhino Mocks. In my opinion, this violates the encapsulation as we are forced to expose methods which are not really supposed to be public. We can overcome this by using the InternalsVisibleTo attribute. This attribute enables us to expose the types and methods which are defined as internal to certain assemblies only.
Apply InternalsVisibleTo attribute
We add the following two lines to the AssemblyInfo.cs of the main project file.
[assembly: InternalsVisibleTo("PartialMocksExample.UnitTest")]
[assembly: InternalsVisibleTo(RhinoMocks.NormalName)]
We are going to access the methods from the UnitTest assembly. So the first line is understandable. The second line is bit confusing. This is required for exposing the internal methods to Rhino Mocks. Internally Rhino Mocks creates a proxy which intercepts the calls to the methods during mocking. Because of this reason we need to make our methods virtual so that the proxy can intercept these calls. Once we have added these lines, we can modify the access levels of the methods which need not be public. Here is the modified code for the CalculateDueAmount method
internal virtual void CalculateTotalDueAmount(PhoneBill generateBill)
{
double totalDueAmount = generateBill.BilledAmount - generateBill.DiscountedAmount;
generateBill.TotalDueAmount = Math.Round(totalDueAmount, ROUNDED_DIGITS, MidpointRounding.AwayFromZero);
}
Similarly I have modified the other methods as well from the previous post.
Conclusion
While following unit testing and TDD approach sometimes we are forced to violate some of the principles of encapsulation to satisfy the external tools like Rhino Mocks. Here we saw how we can make use of InternalsVisibleTo attribute to reduce the visibility of the method while testing. I agree that the methods we are mocking here are supposed to be private by default. We need to have a trade off between writing length unit tests or maintainable and more focussed tests. In my experience I have seen many TDD practitioners use internal methods to make use unit tests which are maintainable.
As always the complete working solution is available for download at Dropbox.
Until next time Happy Programming
Further reading
Following book might be helpful in understanding the topics discussed in this post.
No comments:
Post a Comment