如何对返回 JsonResult 的 Action 方法进行单元测试?
如果我有一个像这样的控制器:
[HttpPost]
public JsonResult FindStuff(string query)
{
var results = _repo.GetStuff(query);
var jsonResult = results.Select(x => new
{
id = x.Id,
name = x.Foo,
type = x.Bar
}).ToList();
return Json(jsonResult);
}
基本上,我从存储库中获取内容,然后将其投影到匿名类型的 List
中。
我如何对其进行单元测试?
System.Web.Mvc.JsonResult
有一个名为 Data
的属性,但正如我们所期望的,它的类型为 object
。
那么这是否意味着如果我想测试 JSON 对象是否具有我期望的属性(“id”、“name”、“type”),我必须使用反射?
编辑:
这是我的测试:
// Arrange.
const string autoCompleteQuery = "soho";
// Act.
var actionResult = _controller.FindLocations(autoCompleteQuery);
// Assert.
Assert.IsNotNull(actionResult, "No ActionResult returned from action method.");
dynamic jsonCollection = actionResult.Data;
foreach (dynamic json in jsonCollection)
{
Assert.IsNotNull(json.id,
"JSON record does not contain \"id\" required property.");
Assert.IsNotNull(json.name,
"JSON record does not contain \"name\" required property.");
Assert.IsNotNull(json.type,
"JSON record does not contain \"type\" required property.");
}
但是我在循环中遇到运行时错误,指出“对象不包含 id 的定义”。
当我断点时,actionResult.Data
被定义为匿名类型的 List
,因此我认为如果枚举这些,我就可以检查属性。在循环内部,对象确实有一个名为“id”的属性 - 所以不确定问题是什么。
If I have a controller like this:
[HttpPost]
public JsonResult FindStuff(string query)
{
var results = _repo.GetStuff(query);
var jsonResult = results.Select(x => new
{
id = x.Id,
name = x.Foo,
type = x.Bar
}).ToList();
return Json(jsonResult);
}
Basically, I grab stuff from my repository, then project it into a List<T>
of anonymous types.
How can I unit-test it?
System.Web.Mvc.JsonResult
has a property called Data
, but it's of type object
, as we expected.
So does that mean if I want to test that the JSON object has the properties I expect ("id", "name", "type"), I have to use reflection?
EDIT:
Here's my test:
// Arrange.
const string autoCompleteQuery = "soho";
// Act.
var actionResult = _controller.FindLocations(autoCompleteQuery);
// Assert.
Assert.IsNotNull(actionResult, "No ActionResult returned from action method.");
dynamic jsonCollection = actionResult.Data;
foreach (dynamic json in jsonCollection)
{
Assert.IsNotNull(json.id,
"JSON record does not contain \"id\" required property.");
Assert.IsNotNull(json.name,
"JSON record does not contain \"name\" required property.");
Assert.IsNotNull(json.type,
"JSON record does not contain \"type\" required property.");
}
But I get a runtime error in the loop, stating "object does not contain a definition for id".
When I breakpoint, actionResult.Data
is defined as a List<T>
of anonymous types, so I figure if I enumerate through these, I can check the properties. Inside the loop, the object does have a property called "id" - so not sure what the issue is.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我知道我对这些人有点晚了,但我发现了为什么动态解决方案不起作用:
JsonResult
返回一个匿名对象,默认情况下,这些是内部
code>,因此需要使它们对测试项目可见。引自: http://weblogs.asp.net/gunnarpeipman/archive/2010/07/24/asp-net-mvc-using-dynamic-type-to-test-controller- actions-returning-jsonresult.aspx
我认为将这个记录下来会很好。就像魅力一样工作
I know I'm a bit late on this guys, but I found out why the dynamic solution wasn't working:
JsonResult
returns an anonymous object and these are, by default,internal
, so they need to be made visible to the tests project.Quoted from: http://weblogs.asp.net/gunnarpeipman/archive/2010/07/24/asp-net-mvc-using-dynamic-type-to-test-controller-actions-returning-jsonresult.aspx
I thought it would be nice to have this one for the record. Works like a charm
RPM,你看起来是正确的。关于动态,我还有很多东西需要学习,而且我也无法让 Marc 的方法发挥作用。这就是我之前的做法。您可能会发现它很有帮助。我刚刚编写了一个简单的扩展方法:
然后我只使用它对我的 Json 数据进行断言:
RPM, you look to be correct. I still have much to learn about
dynamic
and I cannot get Marc's approach to work either. So here is how I was doing it before. You may find it helpful. I just wrote a simple extension method:Then I just use that to do assertions on my Json data:
我来晚了一点,但我创建了一个小包装器,让我可以使用
动态
属性。截至此答案,我已经在 ASP.NET Core 1.0 RC2 上进行了此工作,但我相信如果您将resultObject.Value
替换为resultObject.Data
它应该适用于非- 核心版本。用法,假设有以下控制器:
测试(xUnit):
I'm a bit late to the party, but I created a little wrapper that lets me then use
dynamic
properties. As of this answer I've got this working on ASP.NET Core 1.0 RC2, but I believe if you replaceresultObject.Value
withresultObject.Data
it should work for non-core versions.Usage, assuming the following controller:
The test (xUnit):
这是我使用的一个,也许对任何人都有用。它测试返回 JSON 对象以在客户端功能中使用的操作。它使用 Moq 和 FluentAssertions。
Here's one I use, perhaps it is of use to anyone. It tests an action that returns a JSON object for use in clientside functionality. It uses Moq and FluentAssertions.
我的解决方案是编写扩展方法:
My solution is to write the extension method:
我扩展了 Matt Greer 的解决方案,并提出了这个小扩展:
我只是运行单元测试,如下所示:
- 设置预期数据结果:
- 断言结果:
I extend the solution from Matt Greer and come up with this small extension:
And i just run the unittest as this:
- Set the expected data result:
- Assert the result:
如果在测试中你知道 Json 数据结果到底应该是什么,那么你可以这样做:
PS 这将是如果你使用了 FluentAssertions.Mvc5 - 但将其转换为你想要的任何测试工具应该不难使用。
If in the test you know what exactly the Json data result should be then you can just do something like this:
P.S. This would be if you had used FluentAssertions.Mvc5 - but it shouldn't be hard to convert it to whatever testing tools you use.
这就是我断言的方式
This is how I assert it
您可以将
JsonResult
的 value 属性转换为已知类型的实例,然后只需访问它的属性即可。下面是扩展方法的使用示例:
You can convert the value property of the
JsonResult
into an instance of a known type and then simply access it's properties.below is an example of the use of the extension method: