Search code examples
c#unit-testingxmlreader

XmlReader.Name returning empty string on subsequent calls


I'm currently working with .NET 3.5 for Windows CE. The XmlReader implementation is custom, belonging to the device manufacturer. With this in mind, it's possible the XmlReader just plain sucks.

I have the following test code:

[TestFixture]
public class XmlUtilsTest
{
    private const string EXAMPLE_XML =
    "<Level1>"
        + "<Level2>"
        + "</Level2>"
        + "<Level2>"
            + "<Level3>Some text</Level3>"
        + "</Level2>"
    + "</Level1>"; 

    [Test]
    public void GetElementsAtPathTest()
    {
        IEnumerable<XmlReader> results = XmlUtils.GetElementsAtPath(EXAMPLE_XML, "Level1", "Level2");
        XmlReader[] readers = results.ToArray();

        Assert.AreEqual(2, readers.Length);
        Assert.AreEqual("Level2", readers[0].Name);
        Assert.AreEqual("Level2", readers[1].Name);
    }
}

For the following method:

public static IEnumerable<XmlReader> GetElementsAtPath(string xml, params string[] path)
{
    using (XmlReader reader = new XmlReader(xml))
    {
        if (!MoveToElementAtPath(reader, path))
            yield break;

        string siblingName = path[path.Length - 1];

        do
        {
            XmlReader output = reader.ReadSubtree();
            output.Read();

            PrintLine(output.Name + " " + output.NodeType);

            yield return output;
        }
        while (reader.ReadToNextSibling(siblingName));
    }
}

Printing in my do-while loop gives me the output I expect:

Level2 Element
Level2 Element

However the tests fail:

Failed : GetElementsAtPathTest
  Expected string length 6 but was 0. Strings differ at index 0.
  Expected: "Level2"
  But was:  <string.Empty>

Somehow, between running the method and asserting the results, the state of XmlReader.Name has changed.

I assume I'm making some silly mistake here, but I've been staring at this for a couple hours and can't see anything obvious. Any clues?


Solution

  • Another 30 mins of fighting this thing and it turns out ReadSubtree() is NOT returning a new object. By calling ToArray on the IEnumerable the test is inadvertantly reading to the end of the document.

    //XmlReader output = reader.ReadSubtree();
    XmlReader output = new XmlReader(reader.ReadOuterXml());