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 |