单元测试中ActionResult的问题无法在POST返回值上Assert.Equal(asp.net core mvc web api)

问题描述 投票:0回答:3

我是测试 .net core Web API 的新手,并且正在努力测试 API 上的 POST 方法。我可以断言返回的 ActionResult 的类型,但我似乎无法弄清楚如何将结果与我正在创建的固定装置进行比较。

我已经调试了单元测试,发现 CreatedAtAction 调用返回了一个 ActionResult。顶层值为空。但是,结果的值有该项目。

我觉得我错过了演员表或其他东西,我的代码应该期待 CreatedAtActionResult 或其他东西,但我似乎不知道如何让它工作。

这是我的控制器的 (POST) 方法:

        [HttpPost]
        public async Task<ActionResult<TodoItem>> AddTodoItem(TodoItem item)
        {
            _context.TodoItems.Add(item);
            await _context.SaveChangesAsync();

            return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);
        }

这是我的单元测试:

        [Fact]
        public async Task PostTodoItem_ShouldPass()
        {
            var fixture = new Fixture();
            var item = fixture.Create<TodoItem>();
            var result = await _controller.AddTodoItem(item);
            Assert.IsType<ActionResult<TodoItem>>(result); // WORKS
            Assert.Equal(item, result.Value); // DOESN'T WORK!!
        }

我正在使用 Autofixture 和 EF 内存数据库进行测试。所有这些都是在单元测试之前运行的共享数据库固定类中设置的。

这是我的调试器输出。

debugger output

c# asp.net-web-api .net-core xunit
3个回答
8
投票

这似乎是对象模型中的一个奇怪现象。但我不知道原因。 您调用 CreatedAtAction ,它会返回 CreatedAtActionResult。它有一个 Value 属性,它是一个对象。这就是您将 TodoItem 传递到的内容,您可以在调试器输出中看到它。

这个类不继承自 ActionResult< T>,但这就是你的函数返回的内容。 ActionResult< T> 确实有一个隐式运算符,允许将任何类型转换为它,并且该运算符适用于 ActionResult 对象(非通用)。

因此,当编译器看到您返回 CreatedAtActionResult 时,它需要将其转换为 ActionResult< T> ,以便从 ActionResult 调用隐式转换(如 CreatedAtActionResult : ObjectResult : ActionResult)。

因此,要获得您想要的比较的待办事项,您需要:

 Assert.Equal(item, (result.Result as CreatedAtActionResult).Value); // SHOULD WORK!!

2
投票

Assert.Equal(item, result.Value); // 不起作用!!

Assert.Equal(item, ((ObjectResult)actual.Result).Value); // 试试这个应该可以工作


0
投票

我将 @shrinith-sanil 答案包装到扩展中,以便轻松地在我的所有控制器中重用。谢谢!

public static class ActionResultExtensions
{
    /// <summary>
    /// Becuase controllers return an ActionResult instead of ObjectResult, some fancy casting must be done. 
    /// https://stackoverflow.com/questions/57929044/trouble-with-actionresult-in-unit-test-cant-assert-equal-on-post-return-value
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="task"></param>
    /// <returns></returns>
    public static async Task<T> UnwrapAsync<T>(this Task<ActionResult<T>> task) where T : class
    {
        var result = await task;
        var objectResult = result.Result as ObjectResult;
        var value = objectResult.Value as T;

        return value;
    }
© www.soinside.com 2019 - 2024. All rights reserved.