在 ASP.NET Core 控制器中模拟 HttpRequest

Posted

技术标签:

【中文标题】在 ASP.NET Core 控制器中模拟 HttpRequest【英文标题】:Mock HttpRequest in ASP.NET Core Controller 【发布时间】:2018-10-11 12:10:48 【问题描述】:

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

我为数据访问注入了一个接口,我可以轻松地模拟它。但是控制器必须检查请求中的标头以获得令牌,当我自己简单地实例化控制器时,该请求似乎不存在,而且它也是仅获取的,所以我什至无法手动设置它。我发现了很多模拟 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。如何注入请求,或使用控制器对其进行初始化?我想我最后的手段是反思,但我真的想避免这种情况。

【问题讨论】:

Mock HttpContext for unit testing a .NET core MVC controller?的可能重复 【参考方案1】:

在创建被测控制器的实例时,请确保分配一个 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 之类的控制器依赖项,并且旨在演示如何提供测试所需的特定于框架的依赖项。

【讨论】:

我还听说不应嘲笑 http-context 进行测试。所以我想强调使用 DefaultHttpContext 的建议,而不是试图模拟它。

以上是关于在 ASP.NET Core 控制器中模拟 HttpRequest的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Core 中的每个操作之前查询数据库以获得角色授权

在 ASP.NET Core 中模拟 IPrincipal

使用模拟的 ASP.NET Core 无法访问用户身份

ASP.Net Core 2.0 FileTable 使用

《ASP.NET Core 6框架揭秘》实例演示[27]:ASP.NET Core 6 Minimal API的模拟实现

ASP.NET Core 动作结果 - ASP.NET Core 基础教程 - 简单教程,简单编程