使用 Mock 对 Exception secario 进行单元测试

Unit test for Exception secario using Mock

我有一个 API,其中 Return 类型是 IActionResult。伪代码如下

public async Task<IActionResult> Getdata()
{
   var result = await _report.Getall(DateTime.UtcNow);
}

我正在尝试为此编写单元测试,如下所示。

[Test]
public async Task Error_code()
{
    _report.Setup(r => r.Getall(It.IsAny<DateTime>())).ThrowsAsync(new Exception("Error Message"));
    var result = await _reportCnt.Getdata(); //_reportCnt is object of the Controller
    Assert.AreEqual("Error Message",reuslt);
}

但我面临的问题是,一旦从 API 中抛出错误,它就不会断言,单元测试失败并显示错误 Exception of type 'System.Exception' was thrown.

这3种方法我都试过了

var result = await _reportCnt.Getdata() as ObjectResult;
var result = await _reportCnt.Getdata() as ActionResult;
var result = await _reportCnt.Getdata() as ExceptionResult;

但不工作,抛出同样的问题。

我在这里遗漏了什么或有什么建议吗?

这是一个测试默认 WeatherForecastController 返回 ActionResult 而不是 IActionResult 的示例。您可以在此处了解这些好处:

https://docs.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-5.0#actionresultt-type

[Authorize]
[ApiController]
[Route("[controller]")]

public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public ActionResult<IEnumerable<WeatherForecast>> Get()
    {
        var rng = new Random();
        return 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();
    }
}

使用 xUnit 进行测试,但您应该能够转换为 NUnit

[Fact]
public void DummyTest()
{
    var logger = Mock.Of<ILogger<WeatherForecastController>>();
    var controller = new WeatherForecastController(logger);

    var result = controller.Get().Value.First();

    Assert.True(result.Date.Date == DateTime.Now.AddDays(1).Date, "Date is current date");

    Assert.Throws<ArgumentOutOfRangeException>(() => controller.Get().Value.ToList()[5]);
}

在你设置你的 mock 以抛出异常之后,你可以期望通过像这样调用被测方法:

[Test]
public void Test1()
{
    _report.Setup(r => r.Getall(It.IsAny<DateTime>())).ThrowsAsync(new Exception("Error Message"));

    var exceptionThrown = Assert.ThrowsAsync<Exception>(async () => await _reportCnt.Getdata());

    Assert.AreEqual("Error Message", exceptionThrown.Message);
}