Microsoft has released C# 9 with .NET 5.0. It has lots of new features. One feature I am particularly excited about is new Record Type in C# 9. We can now define our data classes with less code, and it looks clean.
It also provides synthesized methods to provide value semantics for equality. Which makes unit test verification lot easier. Without the Record Type, if we use Class to define entity and when a new instance is created in a service under test to pass it to another class’s method, then we need to use
It.Is<T>(...) to provide which field values are equal in these instances or write Mock Verification to verify correct instance of the object was passed as parameter.
In this article I have described how C# 9.0 Record Type simplifies unit testing and mocking the dependencies.
Let’s consider a scenario where we have an API endpoint to create new
PersonsController. This endpoint takes a
NewPersonRequest as parameter from post body. It then calls
InsertPerson method of
InsertPerson method applies some business logic and transforms
Person database entity and send it to
InsertPersonInD method of
PersonRepository class, to insert it in the database. Repository method returns a
Person with new
Id if it successfully inserts it in the database. It returns null if not able to insert it.
InsertPerson method transforms
Person in the
PersonResponse and sends back to controller method. Which returns result to client.
We want to write a unit test for
Note: Make sure Projects are using .NET 5.0 Framework.
Now Let’s Discuss Code:
New Person Request Class:
Person Service Interface:
Person Service Implementation
Person Repository Interface
Person Repository Implementation
Person Service Test class
Debug the Test:
Let’s now debug the test. Right click on the test method and select ‘Debug Test’ from the context menu. First break point is on the line where we are adding a mock setup for
InsertPersonInDbStore method. We are setting up these values for
newPerson variable which should be passed as a parameter for this method.
Press F5 key to continue debugging. Next it would throw an exception in the
InsertPerson method of
PersonService class where it calls to
InsertPersonInDbStore. Exception says that the Mock setup can not be found for this method. Although we have done one.
If we hover over the instance then it shows same values for every fields same as the instance created for Mock setup.
So what’s the problem here? It is because the
Person instance was created in Mock and instance created here, does not reference to same memory location and hence .NET does not think they are the same instances.
We can solve this issue by changing Mock setup as below:
This setup will be fine if there are handful of fields, but what if we have 10 or 15 fields and we have to write lots of unit tests, then we have to implement
IEquatable<Person> interface in the
Let’s see how Record type solves this issue without any extra work. Change
record as below:
Or we can also declare it in traditional way
Now run the Test again, and this time it passes without any issue.
As we can see record type reduces not only coding time and number of lines, but also provides many other benefits. Read more about C# 9.0 features here. Please let me know if you have any thoughts about it in the comments below.
Originally published at https://www.sharpprogrammer.net on January 30, 2021.