C# 9.0 : Record Type Simplifies Unit Testing

Aziz Kapadia
4 min readJan 30, 2021
C# 9 Record Type simplifies unit tests

Introduction:

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.

Scenario:

Let’s consider a scenario where we have an API endpoint to create new Person in PersonsController. This endpoint takes a NewPersonRequest as parameter from post body. It then calls InsertPerson method of PersonService class.
InsertPerson method applies some business logic and transforms NewPersonRequest into 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 PersonService class's InsertPerson method.

Note: Make sure Projects are using .NET 5.0 Framework.

Now Let’s Discuss Code:

Persons Controller:

Person Class:

New Person Request Class:

Person Response:

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.

Mock person object

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 Personclass.

Let’s see how Record type solves this issue without any extra work. Change Person class to 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.

Summary:

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.

--

--

Aziz Kapadia

Developer, Blogger, Mathematician having 15+ years of experience in Software development and delivery using C#, ASP.NET, WebAPI, Angular etc.