简体   繁体   English

使用 Moq 模拟 ControllerBase 请求

[英]Mock ControllerBase Request using Moq

I have a Web API in.Net Core 2.2 as below:我有一个 Web API in.Net Core 2.2 如下:

[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;
    }
}

I want to mock the properties "Scheme", "Host" and "PathBase" for my controller action in my unit test.我想在我的单元测试中为我的 controller 操作模拟属性“Scheme”、“Host”和“PathBase”。 I managed to write below code in my unit test method:我设法在我的单元测试方法中编写了以下代码:

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);

However, the mock in last line throws exception as " Request " of " ControllerBase " is non overridable.然而,最后一行的模拟抛出异常,因为“ ControllerBase ”的“ Request ”是不可覆盖的。 I understand the limitation with non virtual properties of abstract classes.我理解抽象类的非虚拟属性的限制。 Is there any workaround for this?有什么解决方法吗?

Moq version is 4.13.0.起订量版本为 4.13.0。

Change approach.改变方法。 Do not mock the subject under test, which in this case is the controller.不要模拟被测对象,在本例中是 controller。

The controller's Request is accessed via the HttpContext which can be set when arranging the test.控制器的Request通过HttpContext访问,可以在安排测试时设置。

For example例如

//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,
};

String expected = "expected value here";

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


//Assert
Assert.AreEqual(expected, actual);

//...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM