How do you unit test ASP.NET Core MVC controllers that return anonymous objects?

I am having problems unit testing ASP.NET Core MVC controllers that return anonymous objects. Unit testing is configured in a separate project and directly calls controller methods from the main project.

Controller methods return IActionResult , but usually these are OkObjectResult and BadRequestObjectResult , which are converted to a JSON response with the corresponding HTTP status code. Anonymous objects are passed as constructor parameters for ObjectResult objects, and it is they who I am trying to make statements against (available through ObjectResult.Value ).

I found this question ( how can I access the internals in asp.net 5 ) that has an answer that says to use dynamics and add

 [assembly: InternalsVisibleTo("Namespace")] 

in AssemblyInfo.cs to allow the test project to access the internal properties of the anonymous object object. However, in recent versions of ASP.NET Core MVC there is no AssemblyInfo.cs, and adding one of them, as suggested in the answers to a related question, also does not work.

Is there any other place to add InternalsVisibleTo or am I missing something?

+8
c # unit-testing anonymous-types asp.net-core-mvc
source share
1 answer

An original idea from this answer with a more general approach. Using a custom DynamicObject as a wrapper to check the value through reflection, there was no need to add 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); } } 

Assuming the following controller

 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); } } 

Tests may look like

 [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."); } } 
+16
source share

All Articles