使用Moq的模拟ControllerBase请求

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

我在.Net Core 2.2中具有如下Web API:

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class SomeController : ControllerBase
{
    [HttpPost]
    public async Task<string> SomeMethodPost()
    {
        string returnUrl = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}/some/redirect";

        //Some Third Part Service Call

        return serviceResult;
    }
}

我想为单元测试中的控制器操作模拟属性“ Scheme”,“ Host”和“ PathBase”。我设法在单元测试方法中编写了以下代码:

var request = new Mock<HttpRequest>(MockBehavior.Strict);
request.Setup(x => x.Scheme).Returns("http");
request.Setup(x => x.Host).Returns(HostString.FromUriComponent("http://localhost:8080"));
request.Setup(x => x.PathBase).Returns(PathString.FromUriComponent("/api"));

var mockHttp = new Mock<ControllerBase>(MockBehavior.Strict);
mockHttp.SetupGet(x => x.Request).Returns(request.Object);

但是,最后一行的模拟抛出异常,因为“ Request”的“ ControllerBase”是不可覆盖的。我了解抽象类的非虚拟属性的局限性。有什么解决方法吗?

Moq版本为4.13.0。

c# unit-testing .net-core moq xunit.net
1个回答
0
投票

更改方法。不要嘲笑被测对象,在这种情况下,该对象是控制器。

通过设置测试时可以设置的Request访问控制器的HttpContext。>>

例如

//Arrange
var request = new Mock<HttpRequest>();
request.Setup(x => x.Scheme).Returns("http");
request.Setup(x => x.Host).Returns(HostString.FromUriComponent("http://localhost:8080"));
request.Setup(x => x.PathBase).Returns(PathString.FromUriComponent("/api"));

var httpContext = Mock.Of<HttpContext>(_ => 
    _.Request == request.Object
);

//Controller needs a controller context 
var controllerContext = new ControllerContext() {
    HttpContext = httpContext,
};
//assign context to controller
var controller = new SomeController(){
    ControllerContext = controllerContext,
};


//Act
var actual = await controller.SomeMethodPost();


//Assert
//...
© www.soinside.com 2019 - 2024. All rights reserved.