I have extended the JsonMediaTypeFormatter
in order to generate "root" objects in the JSON for types that are decorated with a custom attribute.
How would I unit test this formatter? I am especially interested in how to check the WriteToStreamAsync(..)
method.
The free O'Reilly ebook Designing Evolvable Web APIs with ASP.NET has some very useful, specific advice on how to test a MediaTypeFormatter
.
Here is their test method for WriteToStreamAsync
. (This is the approach I take to test WebApiContrib.Formatters.Xlsx and it works well.)
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());
Things to note:
FakeContent
and FakeTransport
are fakes of the HttpContent
and TransportContext
classes respectively, code for which you can find in the article.Task.Wait
is used to block execution until the task returned by WriteToStreamAsync
finishes.MemoryStream
, which can then be read and parsed by a suitable formatter/deserialiser so you can make test assertions.Alternatively, you could write a sample controller implementation, start it running and test using a client to call the controller methods. This is what Chris Missal does in WebApiContrib.Formatting.Bson.
The controller doesn't need to be complicated:
public class TestController : ApiController
{
public Item Get(int id)
{
return new Item { ID = id };
}
// ...
}
Set up the server and client:
[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"));
}
Now, in your tests, call the methods on the client and do what you want with the result:
var response = _client.GetAsync("test/1").Result;
var result = response.Content.ReadAsAsync<Item>(new HashSet<MediaTypeFormatter> {new TestMediaTypeFormatter()}).Result;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With