在 ASP.NET Core 控制器中模拟 HttpRequest [英] Mock HttpRequest in ASP.NET Core Controller
问题描述
我正在 ASP.NET Core 中构建一个 Web API,我想对控制器进行单元测试.
I'm building a Web API in ASP.NET Core, and I want to unit test the controllers.
我为数据访问注入了一个接口,我可以轻松地模拟它.但是控制器必须检查请求中的标头以获取令牌,而当我自己简单地实例化控制器时,该请求似乎并不存在,而且它也是 get-only,所以我什至无法手动设置它.我找到了很多模拟 ApiController 的示例,但这不是 .NET 核心.还有许多关于如何对 .net 核心控制器进行单元测试的教程和示例,但没有一个实际使用 HttpRequest.
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. I found lots of examples to mock an ApiController, but that isn't .NET core. Also many tutorials and examples of how to unit test .net core controllers, but none actually used the HttpRequest.
我构建了一个 MCVE 来演示这一点:
I built an MCVE to demonstrate this:
[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());
}
}
我在我的测试项目中使用了 Moq 和 MSTest,并注入了一个模拟的 IAccessor.如何注入请求,或使用控制器初始化它?我想我的最后手段是反思,但我真的想避免这种情况.
I'm using Moq and MSTest in my test project, and inject a mocked 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.
推荐答案
在创建被测控制器的实例时,确保分配一个包含测试所需依赖项的 HttpContext
练习完成.
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
并将其提供给控制器或仅使用框架提供的 DefaultHttpContext
You could try mocking a HttpContext
and providing that to the controller or just use DefaultHttpContext
provided by the framework
//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();
//...
以上假设您已经知道如何模拟 IAccessor
等控制器依赖项,并且旨在演示如何提供测试所需的特定于框架的依赖项.
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.
这篇关于在 ASP.NET Core 控制器中模拟 HttpRequest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!