2

I am trying to unit test a piece of code which has one of the below line

var datatable = new DataTable();
datatable.Load(datareader);

So I want to pass mocked data reader object in the load method. I want data table class to load my stub values from data reader.

I have done below setup in my test case

var dataReader = new Mock<IDataReader>();

    dataReader.Setup(m => m.FieldCount).Returns(2);
    dataReader.Setup(m => m.GetName(0)).Returns(Column1);
    dataReader.Setup(m => m.GetName(1)).Returns(Column2);

    dataReader.Setup(m => m.GetFieldType(0)).Returns(typeof(string));
    dataReader.Setup(m => m.GetFieldType(1)).Returns(typeof(string));

    dataReader.Setup(m => m.GetOrdinal("First")).Returns(0);
    dataReader.Setup(m => m.GetValue(0)).Returns(ExpectedValue1);
    dataReader.Setup(m => m.GetValue(1)).Returns(ExpectedValue2);

    dataReader.SetupSequence(m => m.Read())
        .Returns(true)
        .Returns(true)
        .Returns(false);

I can see while debugging that my data reader is mocked successfully. But when DataTable.Load is executed. DataTable object does not have any values. I can see that columns names are loaded but do not see any values in rows.Even the row numbers are correct but not values in any of the row.

My guess is DataTable.Load does not use GetValue to fetch from data reader and my test case is setup for GetValue method of data reader. I tried to setup GetString method also but still it did not work. Any idea which method of data reader should I setup so that data table is able to load value correctly?

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
Viru
  • 2,228
  • 2
  • 17
  • 28

1 Answers1

1

I'm a bit late to the party but I found that the following works for me (rows get populated too)

var dataReader = new Mock<DbDataReader>();
dataReader.Setup(c => c.FieldCount).Returns(2);

dataReader.Setup(c => c.GetFieldType(0)).Returns(typeof(string));
dataReader.Setup(c => c.GetFieldType(1)).Returns(typeof(string));

// Columns
dataReader.Setup(c => c.GetName(0)).Returns("Column1");
dataReader.Setup(c => c.GetName(1)).Returns("Column2");

dataReader.Setup(m => m.GetOrdinal("Column1")).Returns(0);

// Rows
// NOTE: Unfortunately this only works for a single row.
dataReader.Setup(c => c.GetValues(It.IsAny<object[]>())).Callback<object[]>(
    (values) =>
        {
            values[0] = "Column1 Value";
            values[1] = "Column2 Value";
        }
).Returns(2);

// Read one row
dataReader.SetupSequence(c => c.Read()).Returns(true).Returns(false);

Not an elegant solution but a very quick workaround that I used as a temp solution.

Ed C
  • 313
  • 1
  • 8