This is a migrated thread and some comments may be shown as answers.

Mocking DataSets

1 Answer 809 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Alessandro
Top achievements
Rank 1
Alessandro asked on 22 Jun 2012, 07:31 PM
I have a method that takes a System.Data.DataSet and uses it to construct an object. I am trying to mock the dataset in order to test that the method constructs the object properly.

The method I am testing is the following:
public Box CreateBoxFromDataSet(DataSet dataSet, int rowNumber = 0)
{
    const int BOX_TABLE = 0;
    const int METADATA_TABLE = 1;
 
    Box box = new Box() {
        ID = Convert.ToInt64(dataSet.Tables[BOX_TABLE].Rows[rowNumber]["BoxID"]),
        Name = dataSet.Tables[BOX_TABLE].Rows[rowNumber]["Name"].ToString()
    };
 
    if (dataSet.Tables.Count > 1)
    {
        foreach(DataRow row in dataSet.Tables[METADATA_TABLE].Rows)
        {
            long propertyID = Convert.ToInt64(row["MetaPropertyID"]);
            string value = NullableConverter.ToString(row["MetadataValue"]);
            box.ApplyMetadata(propertyID, value);
        }
    }
 
    return box;
}

My test is the following:
[TestMethod]
public void CreateBoxFromDataSet_ReturnsBox()
{
    //Arrange
    long expectedID = 300;
    Box actual = null;
    var manager = new BoxManager();
    var dataset = new DataSet();
    dataset.Tables.AddRange(new [] { new DataTable("Box"), new DataTable("Metadata") });
    dataset.Tables[0].Rows.Add(dataset.Tables[0].NewRow());
    dataset.Tables[1].Rows.Add(dataset.Tables[1].NewRow());
    dataset.Tables[2].Rows.Add(dataset.Tables[2].NewRow());
    Mock.Arrange(() => dataset.Tables[0].Rows[0]["BoxID"]).Returns(expectedID);
    Mock.Arrange(() => dataset.Tables[0].Rows[0]["Name"]).Returns("BoxName");
    Mock.Arrange(() => dataset.Tables[1].Rows[0]["MetaPropertyID"]).Returns(700);
    Mock.Arrange(() => dataset.Tables[1].Rows[0]["MetadataValue"]).Returns("MetadataValue");
 
    //Act
    actual = manager.CreateBoxFromDataSet(dataset);
 
    //Assert
    Assert.IsNotNull(actual);
}

When I run this test if fails when data is read from the dataset with the following exception:
 "InvalidCastException : Object cannot be cast from DBNull to other types." 

I have tried mocking the DataSet several different ways and cannot get the test to work.
Before this I attempted to create mock tables using
Mock.Create<DataTable>() and
Mock.Arrange(() => dataset.Tables[0]).Returns(mockTable)
but the test still would fail because dataset.Table[0] would throw a IndexOutOfRangeException.

How can I properly mock a DataSet?

Thanks

1 Answer, 1 is accepted

Sort by
0
Ricky
Telerik team
answered on 28 Jun 2012, 03:39 PM
Hi Alessandro,
Thanks again for contacting us.

I have written the test in the following way which works as expected:

//Arrange
Box actual = null;
 
var manager = new BoxManager();
var dataset = new DataSet();
 
long expectedID = 300;
 
var list = Mock.Create<DataTableCollection>(Constructor.Mocked);
 
var metaDataTable = new DataTable("Metadata");
 
DataRowCollection rows = Mock.Create<DataRowCollection>(Constructor.Mocked);
 
var row = Mock.Create<DataRow>(Constructor.Mocked);
 
Mock.Arrange(() => row["BoxID"]).Returns(expectedID);
Mock.Arrange(() => row["Name"]).Returns("BoxName");
Mock.Arrange(() => row["MetaPropertyID"]).Returns(700);
Mock.Arrange(() => row["MetadataValue"]).Returns("MetadataValue");
 
Mock.Arrange(() => rows[0]).Returns(row);
 
Mock.Arrange(() => metaDataTable.Rows).Returns(rows);
 
Mock.Arrange(() => metaDataTable.Rows.GetEnumerator()).Returns(new List<DataRow> { row }.GetEnumerator());
 
Mock.Arrange(() => list[0]).Returns(metaDataTable);
Mock.Arrange(() => list[1]).Returns(metaDataTable);
 
Mock.Arrange(() => dataset.Tables).Returns(list);
Mock.Arrange(() => dataset.Tables.Count).Returns(2);
 
//Act
actual = manager.CreateBoxFromDataSet(dataset);
 
//Assert
Assert.IsNotNull(actual);

However, it is also possible to write the test using ReturnsCollection feature of JustMock for iterating data in collection. But it was not possible since you have index access code and it won’t raise the GetEnumerator call as it is done by foreach loop.
 

Kind Regards
Ricky
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Tags
General Discussions
Asked by
Alessandro
Top achievements
Rank 1
Answers by
Ricky
Telerik team
Share this question
or