Background
Recently, I came across a situation when writing unit tests while building a Repository class, where I was using IDataReader to read the records from database. The challenge comes in, when trying to mock IDataReader to return the rows as it if the rows are returned from database.
When I started mocking IDataReader, I felt it be more complex (than I originally thought) to cover all scenarios (e.g. multiple data types, nullable and non-nullable columns, etc.). I couldn’t find a good solution over in internet either, appears that, it still remain unanswered in several websites like stack overflow.
If you are practicing TDD when building .NET applications, the chances are more likely that you came across this.
So, I started writing some helper mock which can solve the problem easily, which can also save a lot of time in writing customized mocks.
Later I thought of sharing it as a nuget package for anyone who is in need of it. Below are some of the highlighting features of the package.
- Works with Moq
- Supports most of the data types
(string, int, short, long, float, decimal, double, guid, datetime, bool, char and byte)
And now, let’s look into the usage instructions, which shows how cool and easy it is. You can also refer to the instructions at project site.
Usage Instructions
First, we need to install latest package of MoqExtensions.DataReader
Our initial goal is to build the data, that the reader is supposed to provide (as what it is supposed to, when pulling from a database)
For that, we need to create a DataTable
as below specifying the data
and schema
as supposed to be returned by the sql query
used by IDataReader
var mockDataTable = new MockDataTable();
//Add Columns (schema)
mockDataTable.Columns.Add(new MockDataColumn("Column1", typeof(string)));
mockDataTable.Columns.Add(new MockDataColumn("Column2", typeof(string)));
mockDataTable.Columns.Add(new MockDataColumn("Column3", typeof(string), true));
//Add Rows (data) - column order is important here
mockDataTable.Rows.Add(new MockDataRow("Row1_Column1_Value", "Row1_Column2_Value", "Row1_Column3_Value");
mockDataTable.Rows.Add(new MockDataRow("Row2_Column1_Value", "Row2_Column2_Value", "Row2_Column3_Value");
mockDataTable.Rows.Add(new MockDataRow("Row3_Column1_Value", "Row3_Column2_Value", "Row3_Column3_Value");
mockDataTable.Rows.Add(new MockDataRow("Row4_Column1_Value", "Row4_Column2_Value", "Row4_Column3_Value");
Now that we have the mock data and schema ready, we can create a mock datareader as below using Moq and setup to return the mocked data, using the extension method SetupWithReturn
var reader = new Mock<IDataReader>();
//Setup reader to return the data from datatable
reader.SetupWithReturn(table);
At this point, we are all set to use our mocked IDataReader for unit testing a Repository
or any class that uses it. Sample implementation relating to the above, is given below.
while (reader.Read())
{
models.Add(new Model
{
Column1 = reader.GetString(reader.GetOrdinal("Column1")),
Column2 = reader.GetString(reader.GetOrdinal("Column2")),
Column3 = Convert.IsDBNull(reader.GetOrdinal("Column3")) ? null : reader.GetString(reader.GetOrdinal("Column3"))
});
}
Hope you enjoyed using it!
Source Code Repository
Love helping the community!
comments powered by Disqus