Writting Unit test for SQLDataReader

Ramya Gollapudi 1 Reputation point
2022-01-26T13:06:39.137+00:00

Below is the code which I want to write the unit test. If create the mock object for SqlDataReader - its throwing an error "Parent does not have a default constructor. The default constructor must be explicitly defined.'"

Testclass also included - can someone help to resolve this?

DataColumnReader.cs
public class DataColumnReader : IDataColumnReader
{
private readonly IDateTimeFormatter _dateTimeFormatter;

    public DataColumnReader(IDateTimeFormatter dateTimeFormatter)
    {
        _dateTimeFormatter = dateTimeFormatter;
    }

    public void ReadColumn(
        IDictionary<string, object> dataObject,
        string column,
        SqlDataReader sqlDataReader)
    {
        var ordinal = sqlDataReader.GetOrdinal(column);
        var type = sqlDataReader.GetFieldType(ordinal);
        var value = sqlDataReader[column];

        if (type == typeof(DateTime) && !value.ToString().Equals(string.Empty))
        {
            value = _dateTimeFormatter.Format(value);
        }

        dataObject.Add(column, value);
    }
}

DataColumnReaderTests.cs
public class DataColumnReaderTests
{
[Fact]
public void ReadCOlumnTest()
{
var sqlreaderMock = new Mock<SqlDataReader>();
sqlreaderMock.Setup(x => x["testColumn"]).Returns("testdata123");
var options = Options.Create(new DateTimeFormatterSettings());
var _dateTimeFormatter = new DateTimeFormatter(options);

        var dataColumnsReader = new DataColumnReader(_dateTimeFormatter);

        //Arrange + act

        dataColumnsReader.ReadColumn(null, "testColumn", sqlreaderMock.Object);

    }
}
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,625 questions
Visual Studio Testing
Visual Studio Testing
Visual Studio: A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.Testing: The act or process of applying tests as a means of analysis or diagnosis.
337 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Michael Taylor 51,256 Reputation points
    2022-01-26T15:37:25.407+00:00

    You cannot mock or derive from SqlDataReader. To mock it using something like Moq the library creates a derived type and then overrides the virtual members. If the type doesn't have a public constructor then you get the error you're seeing. SqlDataReader has a single constructor and it is internal. Since it is internal you cannot derive from it and hence cannot mock it either. The only possible workaround that I'm aware of is to use a mocking library that doesn't use derived types and Moq isn't one of them.

    Mocking calls to SQL is mostly a mute point anyway. There is really no unit test that you could create that would provide any level of confidence the code is working without actually talking to the SQL database. For example you could mock the running of a command in SQL but unless you also validated the SQL command (aka it is syntactically correct) then all you've really confirmed is that your code is calling a method on a type. If you need to unit test code against SQL then have your unit test target a SQL database, perhaps an embedded one using SQL CE or something.

    The better approach is to generalize your code to use the more generic ADO.NET interfaces or base types from which SQL and other providers derive. Then you can more easily mock them and verify the general behavior of your code (but again, not really giving you validation of the actual calls). Having tried to mock the base Db- types I can tell you it is very difficult to do with lots of extra code to write. Personally I would use the interfaces because at least that is less code to mock.

    1 person found this answer helpful.
    0 comments No comments