如何测试 XML De-/Serialization

How to test XML De-/Serialization

所以我尝试创建一个非常简单的 XmlFileWriter

public class XmlFileWriter
{
    public void WriteTo<TSerializationData>(string path, TSerializationData data)
    {
        using (StreamWriter streamWriter = new StreamWriter(path))
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(TSerializationData));
            xmlSerializer.Serialize(streamWriter, data);
        }
    }
}

XmlFileReader

public class XmlFileReader
{
    public TSerializationData ReadFrom<TSerializationData>(string path)
    {
        using (StreamReader streamReader = new StreamReader(path))
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(TSerializationData));

            return (TSerializationData) xmlSerializer.Deserialize(streamReader);
        }
    }
}

我想用 xUnit 为它们创建单元测试。由于它们与文件系统耦合,我一直在寻找一种以某种方式模拟它的方法。许多帖子强烈推荐 System.IO.Abstractions 包和额外的 TestingHelpers.

我现在只展示 reader 的测试,因为这两种情况非常相似。这是我目前所拥有的

[Fact]
public void ThrowsExceptionIfPathIsInvalid()
{
    XmlFileReader xmlFileReader = new XmlFileReader();

    // use an empty path since it should be invalid
    Assert.Throws<Exception>(() => xmlFileReader.ReadFrom<object>(string.Empty));
}

[Fact]
public void DeserializesDataFromXmlFile()
{
    // Generate dummy data with default values
    MyDummyClass dummyData = new MyDummyClass();
    XmlFileWriter xmlFileWriter = new XmlFileWriter();
    XmlFileReader xmlFileReader = new XmlFileReader();
    string filePath = "???"; // TODO

    // Generate a new file and use it as a mock file
    xmlFileWriter.WriteTo(filePath, dummyData);

    // Read from that file
    MyDummyClass fileContent = xmlFileReader.ReadFrom<MyDummyClass>(filePath);

    // Compare the result
    Assert.Equal(dummyData, fileContent);
}

我正在努力解耦真正的文件系统。我如何让 XmlSerializer class 使用伪造的文件系统?我安装了抽象包,但我不知道如何在这种情况下使用它(用于读写)。

StreamReader and StreamWriter both have constructors that accept a Stream. I recommend making your method also take streams as parameters, and the your unit tests can supply a MemoryStream containing your test xml as a string (which can be hardcoded), while your actual application can provide a FileStream 即磁盘上的文件。像这样:

public void WriteTo<TSerializationData>(Stream location, TSerializationData data)
{
    // Code here doesn't change
}

public TSerializationData ReadFrom<TSerializationData>(Stream location)
{
    // Code here doesn't change
}

然后在你的测试中你可以做:

using (var ms = new MemoryStream())
{
    using (var sr = new StreamWriter())
    {
        sr.Write("<xml>This is your dummy XML string, can be anything you want</xml>");
    }

    MyDummyClass fileContent = xmlFileReader.ReadFrom<MyDummyClass>(ms);
}

如果你想从文件中读取,你可以这样做:

// Using whatever FileMode/ FileAccess you need
MyDummyClass fileContent;
using (var fs = File.Open(@"C:\Path\To\File.xml", FileMode.Open, FileAccess.Read))
{
    fileContent = xmlFileReader.ReadFrom<MyDummyClass>(fs);
}