How to unit test an Action method which returns JsonResult?

前端 未结 8 1921
我在风中等你
我在风中等你 2020-12-13 12:38

If I have a controller like this:

[HttpPost]
public JsonResult FindStuff(string query) 
{
   var results = _repo.GetStuff(query);
   var jsonResult = results         


        
相关标签:
8条回答
  • 2020-12-13 12:54

    This is how I assert it

    foreach (var item in jsonResult.Data as dynamic) {
        ((int)item.Id).ShouldBe( expected Id value );
        ((string)item.name).ShouldBe( "expected name value" );
    }
    
    0 讨论(0)
  • 2020-12-13 12:56

    If in the test you know what exactly the Json data result should be then you can just do something like this:

    result.Data.ToString().Should().Be(new { param = value}.ToString());
    

    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.

    0 讨论(0)
  • 2020-12-13 12:57

    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.

    Open your ASP.NET MVC application project and find AssemblyInfo.cs from folder called Properties. Open AssemblyInfo.cs and add the following line to the end of this file.

    [assembly: InternalsVisibleTo("MyProject.Tests")]
    

    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

    0 讨论(0)
  • 2020-12-13 13:00

    My solution is to write the extension method:

    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);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-13 13:03

    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 replace resultObject.Value with resultObject.Data it should work for non-core versions.

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

    Usage, assuming the following controller:

    public class FooController : Controller
    {
        public IActionResult Get()
        {
            return Json(new {Bar = "Bar", Baz = "Baz"});
        }
    }
    

    The test (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);
    
    0 讨论(0)
  • 2020-12-13 13:04

    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.

    [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);
    }
    
    0 讨论(0)
提交回复
热议问题