Note that there are some explanatory texts on larger screens.

plurals
  1. PONancyFX: How do I deserialize dynamic types via BrowserResponse.Body.DeserializeJson (unit tests)
    text
    copied!<p>I have the following NancyFX unit test. I use the <a href="http://shouldly.github.com/" rel="nofollow noreferrer">Shouldly</a> assertion library to give the set of extensions methods that start <code>.Should---</code></p> <pre><code>[Fact] public void Assessment__Should_return_assessment_state_for_specified_user() { const AssessmentState assessmentState = AssessmentState.Passed; var user = Fake.Mentor(); using (var db = Fake.Db()) { db.Save(user); Fake.Assessment(user.Id, db, assessmentState); db.ClearStaleIndexes(); } var response = Fake.Browser(user.UserName, user.Password) .Get("/assessment/state/" + user.Id, with =&gt; with.HttpRequest()); //var result = (dynamic)body.DeserializeJson&lt;ExpandoObject&gt;(); var result = (dynamic) JsonConvert.DeserializeObject&lt;ExpandoObject&gt;(response.Body.AsString()); result.ShouldNotBe(null); ((AssessmentState) result.State).ShouldBe(assessmentState); } </code></pre> <p>This test calls a <code>AssessmentService</code> uri defined as <code>/assessment/state/" + user.Id</code> which returns a simple JSON object definition that has a single property <code>State</code> of type (enum) <code>AssessmentState</code>, either <code>Passed</code>, <code>Failed</code> or <code>NotStarted</code>. </p> <p>Here is the service handler so you can see there are no tricks.</p> <pre><code>Get["/assessment/state/{userid}"] = parameters =&gt; { var assessment = AssessmentService.GetByUserId(Db, (string)parameters.userid); return assessment == null ? HttpStatusCode.NotFound : Response.AsJson(new { assessment.State }); }; </code></pre> <p>And here is an example the JSON this service call returns:</p> <pre><code>{"State":1} </code></pre> <p>Everything works fine until I try to Deserialize the JSON returned by the fake Nancy browser. First I tried to use the built in method provided by Nancy's <code>BrowserResponse.Body</code> object:</p> <pre><code>var result = (dynamic)response.Body.DeserializeJson&lt;ExpandoObject&gt;(); </code></pre> <p>This deserializes to an empty object. Which is no good. However, if we use the Newtonsoft equivalent then everything is fine (almost).</p> <pre><code>var result = (dynamic) JsonConvert.DeserializeObject&lt;ExpandoObject&gt;(response.Body.AsString()); </code></pre> <p>The JSON deserialization now works and so the following Shouldly assertion passes with flying colours:</p> <pre><code>((AssessmentState) result.State).ShouldBe(assessmentState); </code></pre> <p>However, for reasons that I suspect have to do with anonymous types, the following line fails at run-time (it compiles fine).</p> <pre><code>result.ShouldNotBe(null); </code></pre> <p><img src="https://i.stack.imgur.com/MoFuu.png" alt="Shouldly Exception"></p> <p>That is quite a lot of information. Let me distil it down to two questions:</p> <ol> <li><p>Why does Nancy's built in JSON deserializer not work given that the Newtonsoft version does?</p></li> <li><p>How do I work with the dynamic types generated by the JSON de-serialisation so that the Shouldly extension methods do not cause a run-time exception?</p></li> </ol> <p>Thanks</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload