如何单元测试Core MVC控制器动作是否调用ControllerBase.Problem() [英] How to unit test whether a Core MVC controller action calls ControllerBase.Problem()

查看:163
本文介绍了如何单元测试Core MVC控制器动作是否调用ControllerBase.Problem()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个从ControllerBase派生的控制器,其动作如下:

We have a controller that derives from ControllerBase with an action like this:

public async Task<ActionResult> Get(int id)
{
  try
  {
    // Logic
    return Ok(someReturnValue);
  }
  catch
  {
    return Problem();
  }
}

我们也有这样的单元测试:

We also have a unit test like this:

[TestMethod]
public async Task GetCallsProblemOnInvalidId()
{
  var result = sut.Get(someInvalidId);

}

但是ControllerBase.Problem()会引发Null引用异常.这是Core MVC框架中的一种方法,因此我真的不知道为什么它会引发错误.我认为可能是因为HttpContext为null,但是我不确定. 是否存在标准化方法来测试控制器应调用Problem()的测试用例? 任何帮助表示赞赏. 如果答案涉及嘲笑:我们使用Moq和AutoFixtrue.

But ControllerBase.Problem() throws a Null Reference Exception. This is a method from the Core MVC framework, so I don't realy know why it is throwing the error. I think it may be because HttpContext is null, but I'm not sure. Is there a standardized way to test a test case where the controller should call Problem()? Any help is appreciated. If the answer involves mocking: we use Moq and AutoFixtrue.

推荐答案

空异常是由于缺少ProblemDetailsFactory

在这种情况下,控制器需要能够通过以下方式创建ProblemDetails实例:

In this case the controller needs to be able to create ProblemDetails instance via

[NonAction]
public virtual ObjectResult Problem(
    string detail = null,
    string instance = null,
    int? statusCode = null,
    string title = null,
    string type = null)
{
    var problemDetails = ProblemDetailsFactory.CreateProblemDetails(
        HttpContext,
        statusCode: statusCode ?? 500,
        title: title,
        type: type,
        detail: detail,
        instance: instance);

    return new ObjectResult(problemDetails)
    {
        StatusCode = problemDetails.Status
    };
}

来源

ProblemDetailsFactory是可设置的属性

public ProblemDetailsFactory ProblemDetailsFactory
{
    get
    {
        if (_problemDetailsFactory == null)
        {
            _problemDetailsFactory = HttpContext?.RequestServices?.GetRequiredService<ProblemDetailsFactory>();
        }

        return _problemDetailsFactory;
    }
    set
    {
        if (value == null)
        {
            throw new ArgumentNullException(nameof(value));
        }

        _problemDetailsFactory = value;
    }
}

来源

在单独测试时可能会被模拟和填充.

that could be mocked and populated when testing in isolation.

[TestMethod]
public async Task GetCallsProblemOnInvalidId() {
    //Arrange
    var problemDetails = new ProblemDetails() {
        //...populate as needed
    };
    var mock = new Mock<ProblemDetailsFactory>();
    mock
        .Setup(_ => _.CreateProblemDetails(
            It.IsAny<HttpContext>(),
            It.IsAny<int?>(),
            It.IsAny<string>(),
            It.IsAny<string>(),
            It.IsAny<string>(),
            It.IsAny<string>())
        )
        .Returns(problemDetails)
        .Verifyable();

    var sut = new MyController(...);
    sut.ProblemDetailsFactory = mock.Object;

    //...

    //Act
    var result = await sut.Get(someInvalidId);

    //Assert
    mock.Verify();//verify setup(s) invoked as expected

    //...other assertions
}

这篇关于如何单元测试Core MVC控制器动作是否调用ControllerBase.Problem()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆