繁体   English   中英

在ASP.NET Core Controller中模拟HttpRequest

[英]Mock HttpRequest in ASP.NET Core Controller

我正在ASP.NET Core中构建Web API,并且想对控制器进行单元测试。

我为数据访问注入了一个接口,我可以轻松地对其进行模拟。 但是控制器必须检查Request的标头中是否有令牌,而当我自己简单地实例化控制器时,该Request似乎不存在,并且它也是get-only的,因此我什至无法手动设置它。 我发现了许多示例来模拟ApiController,但这不是.NET核心。 关于如何对.net核心控制器进行单元测试的许多教程和示例,但实际上都没有使用HttpRequest。

我建立了一个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());

    }
}    

我在测试项目中使用Moq和MSTest,然后注入模拟的IAccessor。 如何注入请求,或使用控制器初始化请求? 我想我的最后选择是反思,但我真的想避免这种情况。

创建要测试的控制器的实例时,请确保分配一个HttpContext ,其中包含要执行的测试所需的依赖关系。

您可以尝试模拟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();

//...

上面的假设假设您已经知道如何模拟IAccessor之类的控制器依赖关系,并且旨在演示如何提供测试所需的特定于框架的依赖关系。

暂无
暂无

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

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