producesresponsetype net mvc modelo iactionresult crear asp c# unit-testing asp.net-core-mvc anonymous-types

c# - modelo - ¿Cómo prueba los controladores ASP.NET Core MVC que devuelven objetos anónimos?



producesresponsetype (1)

Idea original de esta respuesta con un enfoque más genérico. Al usar un DynamicObject personalizado como envoltorio para inspeccionar el valor a través de la reflexión, no fue necesario agregar el InternalsVisibleTo

public class DynamicObjectResultValue : DynamicObject, IEquatable<DynamicObjectResultValue> { private readonly object value; public DynamicObjectResultValue(object value) { this.value = value; } #region Operators public static bool operator ==(DynamicObjectResultValue a, DynamicObjectResultValue b) { // If both are null, or both are same instance, return true. if (System.Object.ReferenceEquals(a, b)) { return true; } // If one is null, but not both, return false. if (ReferenceEquals((object)a, null) || ReferenceEquals((object)b, null)) { return false; } // Return true if the fields match: return a.value == b.value; } public static bool operator !=(DynamicObjectResultValue a, DynamicObjectResultValue b) { return !(a == b); } #endregion public override IEnumerable<string> GetDynamicMemberNames() { return value.GetType().GetProperties().Select(p => p.Name); } public override bool TryGetMember(GetMemberBinder binder, out object result) { //initialize value result = null; //Search possible matches and get its value var property = value.GetType().GetProperty(binder.Name); if (property != null) { // If the property is found, // set the value parameter and return true. var propertyValue = property.GetValue(value, null); result = propertyValue; return true; } // Otherwise, return false. return false; } public override bool Equals(object obj) { if (obj is DynamicObjectResultValue) return Equals(obj as DynamicObjectResultValue); // If parameter is null return false. if (ReferenceEquals(obj, null)) return false; // Return true if the fields match: return this.value == obj; } public bool Equals(DynamicObjectResultValue other) { // If parameter is null return false. if (ReferenceEquals(other, null)) return false; // Return true if the fields match: return this.value == other.value; } public override int GetHashCode() { return ToString().GetHashCode(); } public override string ToString() { return string.Format("{0}", value); } }

Asumiendo el siguiente controlador

public class FooController : Controller { public IActionResult GetAnonymousObject() { var jsonResult = new { id = 1, name = "Foo", type = "Bar" }; return Ok(jsonResult); } public IActionResult GetAnonymousCollection() { var jsonResult = Enumerable.Range(1, 20).Select(x => new { id = x, name = "Foo" + x, type = "Bar" + x }).ToList(); return Ok(jsonResult); } }

Las pruebas podrían parecerse

[TestMethod] public void TestDynamicResults() { //Arrange var controller = new FooController(); //Act var result = controller.GetAnonymousObject() as OkObjectResult; //Assert dynamic obj = new DynamicObjectResultValue(result.Value); Assert.IsNotNull(obj); Assert.AreEqual(1, obj.id); Assert.AreEqual("Foo", obj.name); Assert.AreEqual(3, obj.name.Length); Assert.AreEqual("Bar", obj.type); } [TestMethod] public void TestDynamicCollection() { //Arrange var controller = new FooController(); //Act var result = controller.GetAnonymousCollection() as OkObjectResult; //Assert Assert.IsNotNull(result, "No ActionResult returned from action method."); dynamic jsonCollection = result.Value; foreach (dynamic value in jsonCollection) { dynamic json = new DynamicObjectResultValue(value); 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."); } }

Estoy teniendo problemas para probar unidades Controladores ASP.NET Core MVC que devuelven objetos anónimos. La prueba unitaria se configura en un proyecto separado y llama directamente a los métodos del controlador desde el proyecto principal.

Los métodos del controlador devuelven IActionResult pero normalmente estos son objetos OkObjectResult y BadRequestObjectResult que se traducen en una respuesta JSON con el código de estado HTTP apropiado. Los objetos anónimos se pasan como los parámetros del constructor para los objetos ObjectResult y estoy tratando de hacer aserciones contra estos (accesibles a través de ObjectResult.Value ).

Encontré esta pregunta ( ¿cómo puedo acceder a internos en asp.net 5 ) que tiene una respuesta que dice usar dinámica y agregar

[assembly: InternalsVisibleTo("Namespace")]

a AssemblyInfo.cs para permitir que el proyecto de prueba acceda a las propiedades de objeto interno de los objetos anónimos. Sin embargo, las últimas versiones de ASP.NET Core MVC no tienen AssemblyInfo.cs y agregar uno como se sugiere en las respuestas a la pregunta vinculada tampoco funciona.

¿Hay ahora una ubicación diferente para agregar InternalsVisibleTo o me falta algo?