【问题标题】:Unit testing a custom Web API MediaTypeFormatter对自定义 Web API MediaTypeFormatter 进行单元测试
【发布时间】:2013-08-16 08:03:44
【问题描述】:

我有extended the JsonMediaTypeFormatter 以便在JSON 中为decorated with a custom attribute 类型生成“根”对象。

如何对这个格式化程序进行单元测试?我对如何检查WriteToStreamAsync(..) 方法特别感兴趣。

【问题讨论】:

  • 你能将生成的输出与预期的输出进行比较吗?只需检查您的根元素是否按预期生成(即使文件内容比较也应该完成这项工作)。只要格式化程序产生您期望的结果,通常就无需测试其内部结构。
  • 我还是想测试一下...
  • 这是我的测试代码 - 在 stream.Position = 0...
  • 我用你的代码创建了一个项目。我使用 NUnit 而不是 MSTest。我创建了一个名为TestItem 的类,其中一个属性为Property,并运行了您的代码。 stream.Position 是 30。当我调试时,我看到 rootFieldName 为空,这意味着它调用 base.WriteToStreamAsync 而不是您的代码。调试时看到了什么?你在TestItem 课堂上放了什么?你的rootFieldName是什么?

标签: unit-testing asp.net-web-api mediatypeformatter


【解决方案1】:

免费的 O'Reilly 电子书 Designing Evolvable Web APIs with ASP.NET 提供了一些关于 how to test a MediaTypeFormatter 的非常有用的具体建议。

这是他们对WriteToStreamAsync 的测试方法。 (这是我对test WebApiContrib.Formatters.Xlsx 采取的方法,效果很好。)

var ms = new MemoryStream();

var content = new FakeContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/atom+xml");

var formatter = new SyndicationMediaTypeFormatter();

var task = formatter.WriteToStreamAsync(typeof(List<ItemToSerialize>),
  new List<ItemToSerialize> { new ItemToSerialize { ItemName = "Test" }},
  ms,
  content,
  new FakeTransport()
);

task.Wait();

ms.Seek(0, SeekOrigin.Begin);

var atomFormatter = new Atom10FeedFormatter();
atomFormatter.ReadFrom(XmlReader.Create(ms));

Assert.Equal(1, atomFormatter.Feed.Items.Count());

注意事项:

  • FakeContentFakeTransport 分别是 HttpContentTransportContext 类的仿制品,您可以在文章中找到它们的代码。
  • Task.Wait 用于阻塞执行,直到WriteToStreamAsync 返回的任务完成。
  • 格式化程序的输出被写入MemoryStream,然后可以由合适的格式化程序/反序列化程序读取和解析,以便您进行测试断言。

或者,您可以编写一个示例控制器实现,启动它运行并使用客户端进行测试以调用控制器方法。这就是 Chris Missal 在WebApiContrib.Formatting.Bson 中所做的。

控制器不需要复杂:

public class TestController : ApiController
{
    public Item Get(int id)
    {
        return new Item { ID = id };
    }
    // ...
}

设置服务器和客户端:

[TestFixtureSetUp]
public void fixture_init()
{
    var config = new HttpConfiguration();
    config.Formatters.Add(new TestMediaTypeFormatter());
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "{controller}/{id}",
        defaults: new {id = RouteParameter.Optional}
    );

    var server = new HttpServer(config);

    _client = new HttpClient(server);
    _client.BaseAddress = new Uri("http://www.test.com/");
    _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/bson"));
}

现在,在您的测试中,调用客户端上的方法并对结果执行您想要的操作:

var response = _client.GetAsync("test/1").Result;
var result = response.Content.ReadAsAsync<Item>(new HashSet<MediaTypeFormatter> {new TestMediaTypeFormatter()}).Result;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2017-06-02
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多