JsonResult를 반환하는 액션 메서드를 유닛 테스트하는 방법
다음과 같은 컨트롤러가 있는 경우:
[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<T>익명의 타입입니다.
유닛 테스트는 어떻게 해야 하나요?
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.");
}
그러나 루프에서 "object에 id에 대한 정의가 포함되어 있지 않습니다"라는 런타임 오류가 발생합니다.
내가 중단점을 찍었을 때,actionResult.Data로 정의됩니다.List<T>그래서 이것들을 통해 열거하면 속성을 확인할 수 있을 것 같아요.루프 내에서는 오브젝트에 "id"라는 속성이 있기 때문에 문제가 무엇인지 알 수 없습니다.
조금 늦은 건 알지만 다이내믹 솔루션이 작동하지 않는 이유를 알 수 있었습니다.
JsonResult는 어나니머스 오브젝트를 반환합니다.이러한 오브젝트는 디폴트로 다음과 같습니다.internal따라서 테스트 프로젝트에서 볼 수 있도록 해야 합니다.
ASP를 엽니다.NET MVC 응용 프로그램 프로젝트 및 검색
AssemblyInfo.cs[ Properties ]폴더에서 선택합니다.AssemblyInfo.cs 를 열고 이 파일의 끝에 다음 행을 추가합니다.
[assembly: InternalsVisibleTo("MyProject.Tests")]
이걸 공식적으로 하면 좋을 것 같아서요.마법처럼 기능하다
RPM, 당신 말이 맞는 것 같아요.나는 아직 배울 것이 많다.dynamic마크의 접근법도 이해가 안 돼요그래서 이게 내가 전에 했던 방법이야.도움이 될 거예요.간단한 확장 방법을 작성했습니다.
public static object GetReflectedProperty(this object obj, string propertyName)
{
obj.ThrowIfNull("obj");
propertyName.ThrowIfNull("propertyName");
PropertyInfo property = obj.GetType().GetProperty(propertyName);
if (property == null)
{
return null;
}
return property.GetValue(obj, null);
}
그리고 Json 데이터에 대한 어설션을 수행할 때 사용합니다.
JsonResult result = controller.MyAction(...);
...
Assert.That(result.Data, Is.Not.Null, "There should be some data for the JsonResult");
Assert.That(result.Data.GetReflectedProperty("page"), Is.EqualTo(page));
파티에 조금 늦었지만, 작은 포장지를 만들어서dynamic특성.이 답변으로 ASP에서 작업을 하고 있습니다.NET Core 1.0 RC2를 대체하면resultObject.Value와 함께resultObject.Data비코어 버전에서는 동작합니다.
public class JsonResultDynamicWrapper : DynamicObject
{
private readonly object _resultObject;
public JsonResultDynamicWrapper([NotNull] JsonResult resultObject)
{
if (resultObject == null) throw new ArgumentNullException(nameof(resultObject));
_resultObject = resultObject.Value;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (string.IsNullOrEmpty(binder.Name))
{
result = null;
return false;
}
PropertyInfo property = _resultObject.GetType().GetProperty(binder.Name);
if (property == null)
{
result = null;
return false;
}
result = property.GetValue(_resultObject, null);
return true;
}
}
사용방법(다음 컨트롤러가 있는 경우)
public class FooController : Controller
{
public IActionResult Get()
{
return Json(new {Bar = "Bar", Baz = "Baz"});
}
}
테스트(xUnit):
// Arrange
var controller = new FoosController();
// Act
var result = await controller.Get();
// Assert
var resultObject = Assert.IsType<JsonResult>(result);
dynamic resultData = new JsonResultDynamicWrapper(resultObject);
Assert.Equal("Bar", resultData.Bar);
Assert.Equal("Baz", resultData.Baz);
여기 제가 쓰는 게 있어요, 아마 누구에게나 유용할 거예요.클라이언트측 기능에서 사용하기 위해 JSON 개체를 반환하는 액션을 테스트합니다.Moq 및 FluentAssentions를 사용합니다.
[TestMethod]
public void GetActivationcode_Should_Return_JSON_With_Filled_Model()
{
// Arrange...
ActivatiecodeController activatiecodeController = this.ActivatiecodeControllerFactory();
CodeModel model = new CodeModel { Activation = "XYZZY", Lifespan = 10000 };
this.deviceActivatieModelBuilder.Setup(x => x.GenereerNieuweActivatiecode()).Returns(model);
// Act...
var result = activatiecodeController.GetActivationcode() as JsonResult;
// Assert...
((CodeModel)result.Data).Activation.Should().Be("XYZZY");
((CodeModel)result.Data).Lifespan.Should().Be(10000);
}
Matt Greer에서 솔루션을 확장하여 다음과 같은 작은 확장을 제안합니다.
public static JsonResult IsJson(this ActionResult result)
{
Assert.IsInstanceOf<JsonResult>(result);
return (JsonResult) result;
}
public static JsonResult WithModel(this JsonResult result, object model)
{
var props = model.GetType().GetProperties();
foreach (var prop in props)
{
var mv = model.GetReflectedProperty(prop.Name);
var expected = result.Data.GetReflectedProperty(prop.Name);
Assert.AreEqual(expected, mv);
}
return result;
}
그리고 다음과 같이 unittest를 실행합니다. - 예상되는 데이터 결과를 설정합니다.
var expected = new
{
Success = false,
Message = "Name is required"
};
- 결과를 주장합니다.
// Assert
result.IsJson().WithModel(expected);
이 솔루션은 확장 방법을 작성하는 것입니다.
using System.Reflection;
using System.Web.Mvc;
namespace Tests.Extensions
{
public static class JsonExtensions
{
public static object GetPropertyValue(this JsonResult json, string propertyName)
{
return json.Data.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public).GetValue(json.Data, null);
}
}
}
테스트에서 Json 데이터 결과가 정확히 무엇인지 알고 있다면 다음과 같은 작업을 수행할 수 있습니다.
result.Data.ToString().Should().Be(new { param = value}.ToString());
추신: FluentAssertions를 사용한 경우입니다.MVC5 - 그러나 사용하는 테스트 툴로 변환하는 것은 어렵지 않습니다.
이렇게 단언합니다
foreach (var item in jsonResult.Data as dynamic) {
((int)item.Id).ShouldBe( expected Id value );
((string)item.name).ShouldBe( "expected name value" );
}
할 수 .JsonResult이미 알려진 유형의 인스턴스로 변환한 다음 해당 속성에 액세스하기만 하면 됩니다.
public static class JsonResultExtensions
{
public static T ExtractType<T>(this JsonResult result)
{
var resultAsJson = JsonSerializer.Serialize(result.Value);
return JsonSerializer.Deserialize<T>(resultAsJson);
}
}
다음으로 확장 방식의 사용 예를 나타냅니다.
MyModel model = jsonResult.ExtractType<MyModel>();
Assert.True(model.Success);
언급URL : https://stackoverflow.com/questions/4989471/how-to-unit-test-an-action-method-which-returns-jsonresult
'programing' 카테고리의 다른 글
| Powershell을 사용하여 JSON 개체를 파일에 저장하는 방법 (0) | 2023.03.06 |
|---|---|
| 각도로 페이지 제목을 설정하는 방법JS (0) | 2023.03.06 |
| 스프링 부트 메모리 사용량을 줄이는 방법 (0) | 2023.03.06 |
| 스프링 부팅에서 enableLoggingRequestDetails='true'를 설정하는 방법 (0) | 2023.03.06 |
| 구성 요소가 제어되지 않는 자동 완성을 제어하도록 변경하고 있습니다. (0) | 2023.03.06 |