Ok()的部分模拟给我“值不能为空”。 (参数“结果”) 参考Controller action return types in ASP.NET Core Web API

在ASP.NET Core Web应用程序API模板项目中,如果创建部分模拟并返回OK(someObject),则始终会收到一条错误消息,提示“值不能为null。 (参数“结果”)”

有趣的是,当我运行应用程序(F5)时,此方法工作正常。

不起作用的是使用Moq的单元测试。然后我得到这个错误。

我正在使用:
.NET Core 3.0(使用2.1时也会出现此错误)。
最新的Moq 4.13.1
最新的xunit 2.4.0

控制器:

library(tidyverse)
library(rvest)

dates <- seq.Date(as.Date("2015-01-01"),as.Date("2015-01-05"),by = "day")   #set to your range
result <- map(dates,~read_lines(paste0("https://www.timeanddate.com/scripts/cityajax.php?n=spain/madrid&mode=historic&hd=",format(.,"%Y%m%d"),"&month=","%m"),"&year=","%Y")))) %>% #read files (html rather than json)
  map(~paste0("<table>",.,"</table>")) %>%           #trick it into thinking it is a table
  map(~read_html(.) %>% html_table()) %>%              #extract table as dataframe
  map2_df(dates,~.x[[1]] %>%                          
            set_names(make.names(.[1,],unique = TRUE)) %>% #sort out column names 
            select(-2) %>%                                  #remove blank column
            slice(2:(n() - 1)) %>%                          #remove first and last row
            mutate(Date = .y)) %>%                          #add date column
  mutate(Time = substr(Time,1,5))                         #remove dates from time column

head(result)
   Time  Temp Weather    Wind      X.1 Humidity Barometer Visibility       Date
1 07:00 -3 °C  Clear. No wind <U+2191>      86% 1033 mbar      16 km 2015-01-01
2 07:30 -2 °C  Clear. No wind <U+2191>      86% 1033 mbar      16 km 2015-01-01
3 08:00 -2 °C  Clear. No wind <U+2191>      86% 1033 mbar      16 km 2015-01-01
4 08:30 -3 °C  Clear. No wind <U+2191>      86% 1034 mbar      16 km 2015-01-01
5 09:00 -2 °C  Sunny. No wind <U+2191>      93% 1034 mbar      16 km 2015-01-01
6 09:30  1 °C  Sunny. No wind <U+2191>      75% 1035 mbar      16 km 2015-01-01
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using microsoft.AspNetCore.Mvc;
using microsoft.Extensions.Logging;

namespace MyTest.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : BaseaccessController
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing","Bracing","Chilly","Cool","Mild","Warm","Balmy","Hot","Sweltering","Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController()
        {
        }

        [HttpGet]
        public async Task<actionResult<WeatherForecast>> Get()
        {
            try
            {
                int userId = 3;

                if (Hasaccess(userId) == false)
                    return Forbid();

                var rng = new Random();
                return Ok(Enumerable.Range(1,5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),TemperatureC = rng.Next(-20,55),Summary = Summaries[rng.Next(Summaries.Length)]
                })
                .ToArray()); // This is where the error happens!
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
}


单元测试:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using microsoft.AspNetCore.Mvc;

namespace MyTest.Controllers
{
    public class BaseaccessController : Controller
    {
        protected virtual bool Hasaccess(int userId)
        {
            return true;
        }
    }
}
qingabc 回答:Ok()的部分模拟给我“值不能为空”。 (参数“结果”) 参考Controller action return types in ASP.NET Core Web API

这是XY problem

首先,将操作定义为返回

public async Task<ActionResult<WeatherForecast>> Get()

还没有等待,它还会尝试返回WeatherForecast

的集合
return Ok(Enumerable.Range(1,5).Select(index => new WeatherForecast
{
    Date = DateTime.Now.AddDays(index),TemperatureC = rng.Next(-20,55),Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray());

第二,如果使用ActionResult<T>,则无需手动执行Ok(..)结果。只需返回预期的对象。

参考Controller action return types in ASP.NET Core Web API

所以我首先建议重构该动作以遵循文档中建议的语法

[HttpGet]
public async Task<ActionResult<WeatherForecast[]>> Get() { //Note the array
    try {
        int userId = 3;

        if (HasAccess(userId) == false)
            return Forbid();

        var rng = new Random();
        WeatherForecast[] results = await Task.Run(() => Enumerable
            .Range(1,5).Select(index => new WeatherForecast {
                Date = DateTime.Now.AddDays(index),Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray()
        );
        return results;
    } catch (Exception ex) {
        throw;
    }
}

测试还应遵循正确的异步语法并声明预期的返回类型

[Fact]
public async Task MyUnitTest() {
    // Arrange
    var mockController = new Mock<WeatherForecastController>() {
        CallBase = true; //so that it can call `HasAccess` without issue
    };

    // Act
    ActionResult<WeatherForecast[]> actionResult = await mockController.Object.Get(); 

    // Assert
    Assert.IsNotNull(actionResult);
    var returnValue = Assert.IsType<WeatherForecast>(actionResult.Value);
}
,

我只需要将模拟控制器更改为此:

var mockController = new Mock<PersonsController>(mockPersonsService.Object) { CallBase = true };

现在可以正常工作。谢谢!! :-)

本文链接:https://www.f2er.com/3118317.html

大家都在问