user1333
user1333

Reputation:

Unit testing a function that outputs via XmlWriter?

I'm trying to get into the unit testing and TDD way of doing things but I've come across a problem I'm not sure what to do with.

I have a collection that saves itself to disk using XDocument and XmlWriter. I know you shouldn't write the file to disk then check it so I had the XmlWriter output to a memory stream then I checked the contents of the memory stream. The function looks like this:

   public void Save()
    {
        using (XmlWriter xmlWriter = XmlWriter.Create(m_StreamProvider.SaveFileStream(m_FilenameProvider.Filename)))
        {
            XDocument xDoc = new XDocument(new XElement("BookmarkCollection",
                    Items.Select(bookmark => new XElement("Bookmark",
                        new XElement("Name", bookmark.Name),
                        new XElement("Link", bookmark.Link),
                        new XElement("Remarks", bookmark.Remarks),
                        new XElement("DateAdded", bookmark.DateAdded),
                        new XElement("DateLastAccessed", bookmark.DateLastAccessed))
                        )
                        ));

            xDoc.Save(xmlWriter);
        }

    }

And the unit test is

[Test]
    public void Save_OneItemCollection_XmlCreatedCorrectly()
    {
        //Arrange
        MemoryStreamProvider streamProvider = new MemoryStreamProvider();
        IBookmarkCollection collection = XBookmarkTestHelpers.GetXBookmarkCollection(streamProvider);

        IBookmark bookmarkToAdd = XBookmarkTestHelpers.GetIBookmark("myLink");
        collection.Add(bookmarkToAdd);

        //Act
        collection.Save();

        //Assert
        streamProvider.WriteStrean.Position = 0;
        String generatedXml = Encoding.Default.GetString(streamProvider.WriteStrean.GetBuffer());

        Assert.IsTrue(String.Equals(generatedXml, m_ExpectedOneItemString), "XML does not match");
    }

The assert here fails too fragile (I know I could use String.Compare() but it would have similar issues.), Am I testing the right thing? Am I mocking the wrong thing?

All input greatly appreciated!

Upvotes: 5

Views: 1493

Answers (2)

Darin Dimitrov
Darin Dimitrov

Reputation: 1039100

The first thing that feels wrong about the Save function is that it actually has two responsibilities: it selects a storage and it serializes an object graph to this storage. I would start by isolating responsibilities:

public void Save(XmlWriter xmlWriter)
{
    XDocument xDoc = new XDocument(new XElement("BookmarkCollection",
        Items.Select(bookmark => new XElement("Bookmark",
            new XElement("Name", bookmark.Name),
            new XElement("Link", bookmark.Link),
            new XElement("Remarks", bookmark.Remarks),
            new XElement("DateAdded", bookmark.DateAdded),
            new XElement("DateLastAccessed", bookmark.DateLastAccessed))
        )
    ));
    xDoc.Save(xmlWriter);
}

public void Save()
{
    using (XmlWriter xmlWriter = XmlWriter.Create(m_StreamProvider.SaveFileStream(m_FilenameProvider.Filename)))
    {
        Save(xmlWriter);
    }
}

As far as the unit test is concerned, you could define an XSD schema and then validate the result XML against this schema and also test that it contains the values you are looking for.

Upvotes: 5

Mark Seemann
Mark Seemann

Reputation: 233197

In such cases, I use XNode.DeepEquals to compare XML instances with each other because it compares structure, not bytes.

Upvotes: 1

Related Questions