简体   繁体   English

在ASP.NET Core Controller中模拟HttpRequest

[英]Mock HttpRequest in ASP.NET Core Controller

I'm building a Web API in ASP.NET Core, and I want to unit test the controllers. 我正在ASP.NET Core中构建Web API,并且想对控制器进行单元测试。

I inject an interface for data access, that I can easily mock. 我为数据访问注入了一个接口,我可以轻松地对其进行模拟。 But the controller has to check the headers in the Request for a token, and that Request doesn't seem to exist when I simply instantiate the controller myself, and it is also get-only, so I can't even manually set it. 但是控制器必须检查Request的标头中是否有令牌,而当我自己简单地实例化控制器时,该Request似乎不存在,并且它也是get-only的,因此我什至无法手动设置它。 I found lots of examples to mock an ApiController, but that isn't .NET core. 我发现了许多示例来模拟ApiController,但这不是.NET核心。 Also many tutorials and examples of how to unit test .net core controllers, but none actually used the HttpRequest. 关于如何对.net核心控制器进行单元测试的许多教程和示例,但实际上都没有使用HttpRequest。

I built an MCVE to demonstrate this: 我建立了一个MCVE来证明这一点:

[Produces("application/json")]
[Route("api/Players")]
public class PlayersController : Controller
{
    private IAccessor accessor;

    public PlayersController(IAccessor ac = null):base()
    {
        accessor = ac ?? AccessorFactory.GetAccessor();
    }

    /// <summary>
    /// Get all players. Must be logged in.
    /// </summary>
    /// <returns>Ok or Unauthorized.</returns>
    [HttpGet]
    public IActionResult Get()
    {
        Player client = accessor.GetLoggedInPlayer(Request.Headers["token"]); // NRE here because Request is null
        if (client == null) return Unauthorized();
        return Ok(accessor.GetAllPlayers());

    }
}    

I'm using Moq and MSTest in my test project, and inject a mocked IAccessor. 我在测试项目中使用Moq和MSTest,然后注入模拟的IAccessor。 How do I inject the Request, or initialize it with the controller? 如何注入请求,或使用控制器初始化请求? I guess my last resort would be reflection, but I really want to avoid that. 我想我的最后选择是反思,但我真的想避免这种情况。

When creating an instance of the controller under test, make sure to assign a HttpContext that contains the required dependencies for the test to be exercised to completion. 创建要测试的控制器的实例时,请确保分配一个HttpContext ,其中包含要执行的测试所需的依赖关系。

You could try mocking a HttpContext and providing that to the controller or just use DefaultHttpContext provided by the framework 您可以尝试模拟HttpContext并将其提供给控制器,或者仅使用框架提供的DefaultHttpContext

//Arrange
var mockedAccessor = new Mock<IAccessor>();
//...setup mockedAccessor behavior

//...

var httpContext = new DefaultHttpContext(); // or mock a `HttpContext`
httpContext.Request.Headers["token"] = "fake_token_here"; //Set header
 //Controller needs a controller context 
var controllerContext = new ControllerContext() {
    HttpContext = httpContext,
};
//assign context to controller
var controller = new PlayersController (mockedAccessor.Object){
    ControllerContext = controllerContext,
};

//Act
var result = controller.Get();

//...

The above assumes you already know how to mock the controller dependencies like IAccessor and was meant to demonstrate how to provide framework specific dependencies needed for the test. 上面的假设假设您已经知道如何模拟IAccessor之类的控制器依赖关系,并且旨在演示如何提供测试所需的特定于框架的依赖关系。

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

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