Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net web api 如何在使用HttpServer的测试中使用格式化程序?_Asp.net Web Api - Fatal编程技术网

Asp.net web api 如何在使用HttpServer的测试中使用格式化程序?

Asp.net web api 如何在使用HttpServer的测试中使用格式化程序?,asp.net-web-api,Asp.net Web Api,在我的Web API应用程序中,我使用HttpServer在单元测试中包含我的控制器,并使用HttpClient直接调用它,例如: [Fact] public void TestMyController() { var config = new HttpConfiguration(); config.Routes.MapHttpRoute("default", "api/{controller}/{action}/{id}", new { id = RouteParameter.

在我的Web API应用程序中,我使用
HttpServer
在单元测试中包含我的控制器,并使用
HttpClient
直接调用它,例如:

[Fact]
public void TestMyController()
{
    var config = new HttpConfiguration();
    config.Routes.MapHttpRoute("default", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });

    var server = new HttpServer(config);
    var client = new HttpClient(server);

    var response = client.GetAsync("http://localhost/api/test/values").Result;
}
我注意到(通过单步调试,并在其他SO帖子中确认),
JsonFormatter
并没有真正运行-它已经初始化,但没有运行。由于此测试没有打开套接字,
HttpClient
通过
HttpMessageHandler
API直接调用
HttpServer
,因此不运行格式化/序列化是有意义的,因为不需要它


在我的例子中,我有一些自定义的格式化/序列化/反序列化代码,这些代码在这些测试中不会被命中,但在真正的web服务器中运行时会被命中。我想在这些测试中使用这些代码;而且,在测试时排除序列化/反序列化代码路径似乎也有风险。对此有什么建议吗?

下面是一个快速示例,说明如何强制格式化程序进行序列化/反序列化。这里我们将
ObjectContent
转换为
StreamContent
。在下面的代码中,对
CopyToAsync
的调用会触发一个路径,在该路径中格式化程序被强制序列化。在反序列化的情况下,为了确保我们通过格式化程序,我们希望内容的类型不是
ObjectContent
,因为
ReadAsAsync
具有内部逻辑,在特殊情况下
ObjectContent
我们希望绕过它

HttpClient client = new HttpClient(new InMemoryHttpContentSerializationHandler(new HttpServer(config)));

MemoryHttpContentSerializationHandler中的公共类:DelegatingHandler { public InMemoryHttpContentSerializationHandler(HttpMessageHandler innerHandler) :base(innerHandler) { } 受保护的覆盖异步任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken) { request.Content=等待ConvertToStreamContentAsync(request.Content); HttpResponseMessage response=await base.SendAsync(请求,取消令牌); response.Content=等待ConvertToStreamContentAsync(response.Content); 返回响应; } 专用异步任务ConvertToStreamContentAsync(HttpContent原始内容) { if(originalContent==null) { 返回null; } StreamContent StreamContent=作为StreamContent的原始内容; if(streamContent!=null) { 返回流内容; } MemoryStream ms=新的MemoryStream(); 等待原始内容。复制到同步(ms); //将流位置重置回0,与上一次CopyToAsync()调用相同, //例如,格式化程序可以将位置设置为末尾 ms.Position=0; streamContent=新的streamContent(毫秒); //从原始内容复制标题 foreach(原始内容标题中的KeyValuePair标题) { streamContent.Headers.TryAddWithoutValidation(header.Key,header.Value); } 返回流内容; } }
您不能直接调用response.Content.LoadIntoBufferAsync()吗.Wait?
LoadIntoBufferAsync
只会导致序列化通过格式化程序…但是如果我们也要执行格式化程序反序列化,那么内容类型必须不同于
ObjectContent
,因为
ReadAsAsync
具有特殊的大小写,它只在其中检索对象内容..非常好的回答-非常感谢。我找到了你的相关博文:在你的回答中,该类被更新为使用async/await。@crimbo:我接受你的编辑时出错了……你能再次提交吗?
public class InMemoryHttpContentSerializationHandler : DelegatingHandler
{
    public InMemoryHttpContentSerializationHandler(HttpMessageHandler innerHandler)
        : base(innerHandler)
    {
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Content = await ConvertToStreamContentAsync(request.Content);

        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

        response.Content = await ConvertToStreamContentAsync(response.Content);

        return response;
    }

    private async Task<StreamContent> ConvertToStreamContentAsync(HttpContent originalContent)
    {
        if (originalContent == null)
        {
            return null;
        }

        StreamContent streamContent = originalContent as StreamContent;

        if (streamContent != null)
        {
            return streamContent;
        }

        MemoryStream ms = new MemoryStream();

        await originalContent.CopyToAsync(ms);

        // Reset the stream position back to 0 as in the previous CopyToAsync() call,
        // a formatter for example, could have made the position to be at the end
        ms.Position = 0;

        streamContent = new StreamContent(ms);

        // copy headers from the original content
        foreach (KeyValuePair<string, IEnumerable<string>> header in originalContent.Headers)
        {
            streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
        }

        return streamContent;
    }
}