Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create a SqlDataReader and provide it with values without having to return a SqlDataReader from another object e.g. SqlCommand.ExecuteReader()

I am writing unit tests for my data access layer. To achieve this I have created a wrapper for SqlCommand (ISqlCommand) so that I can mock its functionality.

ISqlCommand command = _connection.GetSqlCommand(sqlCommand);

In one of the methods I am testing, SqlCommand's ExecuteReader method is being called and I have to return a SqlDataReader.

SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow);

In this same method reader.Read will get called

if (reader.Read())
{
    someVariable = reader.GetString(1);
}

What I want is to be able to return a SqlDataReader object from the mocked command.ExecuteReader() with a value present for me to Read. Can it be done? It seems that SqlDataReader can only be instantiated from an actual SqlCommand.ExecuteReader being run and returning a SqlDataReader. Full relevant code to be tested.

ISqlCommand command = _connection.GetSqlCommand(sqlCommand);

using (command)
{
    SqlDataReader reader =  command.ExecuteReader(CommandBehavior.SingleRow);

    if (reader.Read())
    {
        dbVersion = reader.GetString(1);
    }
}

EDIT: To clear about what I am asking. SqlDatareader has no public constructor. As far as I can tell I cannot write any tests using that class as I cannot instantiate it without making a legitimate call to a database using SqlCommand. Even trying to create an interface of a SqlDataReaderWrapper will no help me as the problem is the same. I am not trying to write an integration test (making actual calls to a DB) and so the DataReader seems impossible to test as is. My question is, is there anything i can do, to put values into a SqlDataReader in this situation?

like image 701
Joseph Devlin Avatar asked Oct 22 '22 21:10

Joseph Devlin


1 Answers

I am assuming you are not using a mocking framework. It would help to do so, but you should probably mock the IDataReader as suggested above. Here is a previous question that uses RhinoMocks. that may help.

Mocking a DataReader and getting a Rhino.Mocks.Exceptions.ExpectationViolationException: IDisposable.Dispose(); Expected #0, Actual #1

Also, I noticed you made an ISqlCommand, I suggest you use IDbCommand at it is the out of the box interface and will make your tests less brittle as it will allow substitution of other command objects if needed.

I just mocked the Data Reader and it runs fine:

 Mock<IDataReader> mockDataReader = new Mock<IDataReader>();
 bool success = true;
 mockDataReader.Setup(x => x.Read())
               .Returns(() => success).Callback(() => success = false);
 Assert.IsTrue(mockDataReader.Object.Read());

Here is a good example: http://www.codeproject.com/Articles/478504/Moq-Mock-Database

like image 134
Jamie Avatar answered Oct 27 '22 09:10

Jamie