Mocking DataSets

2 posts, 0 answers
  1. Alessandro
    Alessandro avatar
    1 posts
    Member since:
    Jun 2012

    Posted 22 Jun 2012 Link to this post

    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

  2. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 28 Jun 2012 Link to this post

    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 >>

  3. DevCraft R3 2016 release webinar banner
Back to Top