如何使用UnitTest自定义MediaTypeFormatter

时间:2016-11-15 20:55:58

标签: c#

public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext)
    {
        //go lookup the concrete for the interface
        var newType = GetNewType(type);
        var newValue = GetNewValue(value, type);

        var serializer = new XmlSerializer(newType);
        return Task.Factory.StartNew(() =>
        {
            using (var streamWriter = new StreamWriter(stream, _encoder))
            {
                var ns = new XmlSerializerNamespaces();
                ns.Add("", "");
                serializer.Serialize(streamWriter, newValue, ns);
            }
        });
    }

此Custom mediatype格式化程序正在尝试序列化xml的命名空间。我试图测试这个方法,但抛出一个错误,无法访问一个封闭的流。有没有办法对这种方法进行单元测试。

2 个答案:

答案 0 :(得分:1)

创建序列化程序的抽象

public interface ISerializer
{
    void Serialize(StreamWriter writer, object value, XmlSerializerNamespaces ns);
}

然后使用构造函数注入向ISerializer的实现注入MediaTypeFormatter(感谢@pep指出)。这使您可以传递虚拟实现。

public class MyMediaTypeFormatter : MediaTypeFormatter
{
    private ISerializer _serializer;
    public MyMediaTypeFormatter(ISerializer serializer)
    {
        _serializer = serializer;
    }
    ...
}

WriteToStreamAsync然后只使用_serializer

public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext)
{
    var newType = GetNewType(type);
    var newValue = GetNewValue(value, type);
    return Task.Factory.StartNew(() => {
        using (var streamWriter = new StreamWriter(stream, _encoder)) {
            var ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            _serializer.Serialize(streamWriter, newValue, ns);
        }
    });
}

可能的实施:

public class MyXmlSerializer<T> : ISerializer
{
    private readonly XmlSerializer _xmlSerializer = new XmlSerializer(typeof(T));

    public void Serialize(StreamWriter writer, object value, XmlSerializerNamespaces ns)
    {
        _xmlSerializer.Serialize(writer, value, ns);
    }
}

可能的假人:

public class DummySerializer : ISerializer
{
    // You can test these properties in the unit test after the call;
    public StreamWriter Writer { get; private set; }
    public object Value { get; private set; }
    public XmlSerializerNamespaces NS { get; private set; }
    public int Calls { get; private set; }

    public void Serialize(StreamWriter writer, object value, XmlSerializerNamespaces ns)
    {
        Writer = writer;
        Value = value;
        NS = ns;
        Calls++;
    }
}

或使用NSubstitute或其他模拟框架。注意:这些框架会在运行时自动创建接口的虚拟实现。

针对接口而不是具体类进行编程不仅增加了代码的灵活性,而且通常也是单元测试的必需条件。

答案 1 :(得分:0)

您是否先尝试打开流然后再使用它?因为除非打开它,否则无法写入文件或从中读取文件。希望这有帮助! :)