Flurl: HttpTest - misused header name?

Created on 19 Jun 2018  路  4Comments  路  Source: tmenier/Flurl

I'm trying to write some unit tests that expect the response headers to be set a specific way. For example, I need to set the Content-Type to text/xml. When I attempt to arrange a test using the HttpTest() object, I get the following error message:

_httpTest = new HttpTest();

_httpTest.RespondWith("<xml></xml>", 401, new Dictionary<string, string>{{ "Content-Type", "text/xml" }});

//test

_httpTest.Dispose();
Test method TestMethod threw exception: 
System.InvalidOperationException: Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.

The test will succeed if I remove Content-Type header and set it to almost anything else, including garbage headers.

bug

Most helpful comment

I did some refactoring so that the test methods piggy-back off the same header normalization logic as the core methods (WithHeader, etc.) In addition to fixing this bug, here are a few other niceties:

  • You can use underscores in place of hyphens in property names of the headers object passed to RespondWith (similar to #44), allowing you to do new { Content_Type = "text/xml" } instead of the clunky Dictionary syntax.

  • New extension methods SetHeader and GetHeaderValue on both HttpRequestMessage and HttpResponseMessage. These allow you to set or get headers without caring whether they're at the request/response message level or content level. Also, the notion of header value as a collection is abstracted away; you just get or set a single value. And SetHeader doesn't validate (it uses TryAddWithoutValidation under the hood). These are rules that Flurl has always used when translating its dumbed-down notion of headers to the HttpClient stack, but now test helpers leverage them too, and the extension methods are public.

This will all be released in 2.3.2.

All 4 comments

TL;DR

It's a bug, here's a work-around:

c# var content = new StringContent("<xml></xml>", Encoding.UTF8, "text/xml"); _httpTest.RespondWith(content, 401);

The bug is related to how the HttpClient world makes a distinction between request-level and content-level headers, and it's a bit unforgiving if you put a "known" header on the wrong one. Flurl's WithHeader and WithHeaders methods work around this explicitly so the developer doesn't need to be concerned about that distinction. (At the raw HTTP level, a request header is a request header.) But HttpTest doesn't piggy-back off the same logic, and it'll fail when you try to add a "content-level" header. I'll need to look into making it work there too.

Thanks for reporting.

@tmenier Thanks for taking a look. I'll mention how I got around this and got my test to pass (although your method looks more succinct).

 _httpTest.RespondWith(
                @"<?xml version=""1.0"" encoding=""utf-8""?><data></data>", 401)
                     .Settings.AfterCall = call => {
                         call.Response.Content.Headers.ContentType.MediaType = "text/xml";
                    };

I did some refactoring so that the test methods piggy-back off the same header normalization logic as the core methods (WithHeader, etc.) In addition to fixing this bug, here are a few other niceties:

  • You can use underscores in place of hyphens in property names of the headers object passed to RespondWith (similar to #44), allowing you to do new { Content_Type = "text/xml" } instead of the clunky Dictionary syntax.

  • New extension methods SetHeader and GetHeaderValue on both HttpRequestMessage and HttpResponseMessage. These allow you to set or get headers without caring whether they're at the request/response message level or content level. Also, the notion of header value as a collection is abstracted away; you just get or set a single value. And SetHeader doesn't validate (it uses TryAddWithoutValidation under the hood). These are rules that Flurl has always used when translating its dumbed-down notion of headers to the HttpClient stack, but now test helpers leverage them too, and the extension methods are public.

This will all be released in 2.3.2.

Was this page helpful?
0 / 5 - 0 ratings