如何 cast/convert 来自 HttpResponseMessage 的匿名类型进行单元测试?

How can I cast/convert an anonymous type from HttpResponseMessage for unit testing?

我的任务是为以下 Web API 2 操作编写单元测试:

public HttpResponseMessage Get()
{
    IEnumerable<KeyValuePair<long, string>> things = _service.GetSomething();
    return ActionContext.Request.CreateResponse(things.Select(x => new 
        { 
            Thing1 = x.Prop1.ToString(), 
            Thing2 = x.Prop2 
        }).ToArray());
}

我正在测试状态代码并且工作正常,但我无法弄清楚如何提取内容数据并对其进行测试。到目前为止,这是我的测试:

[TestMethod]
public void GetReturnsOkAndExpectedType()
{
    var controller = GetTheController();
    var response = controller.Get();
    Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
    dynamic responseContent;
    Assert.IsTrue(response.TryGetContentValue(out responseContent));
    //???? How can I cast/convert responseContent here ????
}

如果我立即调试测试并检查 responseContent window,我会看到这个(我在一个用于测试的假值中有 mocked/stubbed):

{<>f__AnonymousType1<string, string>[1]}
    [0]: { Thing1 = "123", Thing2 = "unit test" }

我可以将其转换为对象数组,但如果我尝试通过它们的 属性 名称提取值,我会收到错误消息(立即再次 window):

((object[])responseContent)[0].Thing1
'object' does not contain a definition for 'Thing1' and no extension method 'Thing1' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

同样,如果我尝试转换和投影到相同形状的匿名类型,它不会编译:

//Thing1 and Thing2 get red-lined here as 'cannot resolve symbol'
var castResult = ((object[]) responseContent).ToList().Select(x => new {x.Thing1, x.Thing2});  

我知道如果我 serialize/deserialize 一切都使用 JsonConvert 之类的东西,我可能可以实现我想做的事情,但这似乎不像 "right" 那样做.我觉得我在这里缺少一些基本的东西。我如何 cast/convert 来自 HttpResponseMessage 的匿名类型进行单元测试?

正如@Daniel 所说J.G。在上面的评论中,一种选择是使用反射来获取属性的值。由于您似乎正在使用 MS 测试框架,另一种选择是使用 PrivateObject class 为您完成一些反射工作。

因此,您可以在测试中执行以下操作:

var poContent = ((object[])responseContent).Select(x => new PrivateObject(x)).ToArray();

Assert.AreEqual("123", poContent[0].GetProperty("Thing1"));
Assert.AreEqual("unit test", poContent[0].GetProperty("Thing2"));