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

Mat*_*ter 2 c# xunit asp.net-web-api .net-core

我是测试 .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);
        }
Run Code Online (Sandbox Code Playgroud)

这是我的单元测试:

        [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!!
        }
Run Code Online (Sandbox Code Playgroud)

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

这是我的调试器输出。

调试器输出

Cia*_*ell 6

这似乎是对象模型中的一个奇怪现象。但我不知道原因。您调用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!!
Run Code Online (Sandbox Code Playgroud)