2

我有以下 NancyFX 单元测试。我使用Shouldly断言库来提供一组扩展方法.Should---

[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 => with.HttpRequest());

    //var result = (dynamic)body.DeserializeJson<ExpandoObject>();
    var result = (dynamic) JsonConvert.DeserializeObject<ExpandoObject>(response.Body.AsString());

    result.ShouldNotBe(null);
    ((AssessmentState) result.State).ShouldBe(assessmentState);
}

此测试调用AssessmentService定义为的 uri,它返回一个简单的 JSON 对象定义,该对象定义具有类型 (enum)/assessment/state/" + user.Id的单个属性,要么,要么。StateAssessmentStatePassedFailedNotStarted

这是服务处理程序,因此您可以看到没有任何技巧。

Get["/assessment/state/{userid}"] = parameters =>
    {
        var assessment = AssessmentService.GetByUserId(Db, (string)parameters.userid);
        return assessment == null ? HttpStatusCode.NotFound : Response.AsJson(new
                                                                        {
                                                                            assessment.State
                                                                        });
    };

这是此服务调用返回的 JSON 示例:

{"State":1}

一切正常,直到我尝试反序列化假 Nancy 浏览器返回的 JSON。BrowserResponse.Body首先,我尝试使用 Nancy对象提供的内置方法:

var result = (dynamic)response.Body.DeserializeJson<ExpandoObject>();

这将反序列化为一个空对象。这不好。但是,如果我们使用 Newtonsoft 等价物,那么一切都很好(几乎)。

var result = (dynamic) JsonConvert.DeserializeObject<ExpandoObject>(response.Body.AsString());

JSON 反序列化现在可以工作,因此以下应该断言通过了出色的结果:

((AssessmentState) result.State).ShouldBe(assessmentState);

但是,由于我怀疑与匿名类型有关的原因,以下行在运行时失败(它编译得很好)。

result.ShouldNotBe(null);

应该例外

这是相当多的信息。让我把它提炼成两个问题:

  1. 鉴于 Newtonsoft 版本可以,为什么 Nancy 内置的 JSON 反序列化器不起作用?

  2. 如何使用 JSON 反序列化生成的动态类型,以便应该扩展方法不会导致运行时异常?

谢谢

4

1 回答 1

4

第一个问题我不能回答,但是WRT Shouldly 和动态类型,Shouldly 的ShouldNotBe方法是object. DLR 不允许您在类型为的对象上调用扩展方法dynamic(因此您会看到运行时绑定程序异常)

我建议如果你想在结果上调用 ShouldNotBe(null) ,你必须将它转换为object第一个(即((object)result).ShouldNotBe(null):)

-X

于 2012-05-12T10:39:47.637 回答