9

I am trying to create a test for some of our webapi calls and I am having difficulties accessing the results. In all of the examples I have viewed they were using OkNegotiatedContentResult. The problem is that in our web api calls we are often times wrapping the data in anonymous objects so we can combine data sets. I am probably overlooking something obvious, but I can't seem to figure out the proper way to inspect the result information to validate it.

WebApi Snippet

var orderInfo = new
{
   Customer = customerInfo,
   Order = orderInfo
}

return Ok(orderInfo);

Api Test Snippet

    [TestMethod]
    public void TestGetOrderInfo()
    {
        var controller = new OrderController(_repo);
        IHttpActionResult results = controller.GetOrderInfo(46);

        Assert.IsNotNull(results);


    }

How can I inspect the results using the OkNegotiatedContentResult when an anonymous type is involved?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
scarpacci
  • 8,957
  • 16
  • 79
  • 144
  • DId you ever get this working? I am having the exact same problem trying to unit test a controller that is returning JSON via `IHttpActionResult` and sees an anonymous type due to having to add a root node prior to the return from the controller. I can't test this, because I can't cast in order to use `OkNegotiatedContentResult` properly. I tried the dynamic approach below without success. – Patrick Mar 27 '16 at 08:43

3 Answers3

12

The reason for the problems with anonymous types is that they are internal types rather than public, so your tests can't use them.

If you add an InternalsVisibleTo attribute to your webapi project you'll then be able to reference the result and its Content via dynamic eg:

[TestMethod]
public void TestGetOrderInfo()
{
    var controller = new OrderController(_repo);
    dynamic results = controller.GetOrderInfo(46);
    dynamic content = results.Content;

    ...

}
Graeme Bradbury
  • 3,693
  • 22
  • 29
  • 4
    I am having this exact same problem with an anonymous type and IHttpActionResult. I have to add a root node to my JSON return so from Web API 2.0 I am doing `return Json(new { User = person });` to get a root node in there named "User". This now returns an anonymous type. I tried to follow your example, but it fails on `dynamic content = results.Content` with ` 'object' does not contain a definition for 'Content` – Patrick Mar 27 '16 at 08:42
  • This helped, but then I got a compiler error "Missing compiler required member 'microsoft.csharp.runtimebinder.binder.convert'", which lead me to https://stackoverflow.com/a/50050820/283895 and now it is fixed. – tgolisch Sep 28 '20 at 19:14
  • I just have to say dynamic are ugly AF. If you really want this make a class that returns your ContentResult typed. – andrecj Dec 30 '21 at 13:09
2

Anonymous objects are internal to the assembly that created them. If you are doing unit testing in a separated assembly (DLL) you will need to explicitly say that you want to share internal values with that assembly using the InternalsVisibleTo attribute.

Corey Ford
  • 145
  • 1
  • 8
1

Patrick found why you are getting error "'object' does not contain a definition for 'Content'". The anonymous type generated by the SUT is internal. Share internals with the test project and you should be able to inspect the anonymous type by doing something like this in the AssemblyInfo.cs in the project: being tested

[assembly: InternalsVisibleTo("Tests.Unit")] 

Found this in article here http://patrickdesjardins.com/blog/how-to-unit-test-a-method-that-return-an-anonymous-type

abatishchev
  • 98,240
  • 88
  • 296
  • 433
santiagovm
  • 83
  • 7