web-dev-qa-db-fra.com

Mock HttpRequest dans ASP.NET Core Controller

Je construis une API Web dans ASP.NET Core et je veux tester les contrôleurs de manière unitaire.

J'injecte une interface d'accès aux données, que je peux facilement simuler. Mais le contrôleur doit vérifier les en-têtes dans la demande de jeton, et cette demande ne semble pas exister lorsque j'instancie simplement le contrôleur moi-même, et elle est également en lecture seule, donc je ne peux même pas la définir manuellement. J'ai trouvé beaucoup d'exemples pour se moquer d'un ApiController, mais ce n'est pas le noyau .NET. De nombreux didacticiels et exemples sur la façon de tester les contrôleurs de base .net, mais aucun n'a réellement utilisé HttpRequest.

J'ai construit un MCVE pour le démontrer:

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

    }
}    

J'utilise Moq et MSTest dans mon projet de test et j'injecte un IAccessor simulé. Comment injecter la demande ou l'initialiser avec le contrôleur? Je suppose que mon dernier recours serait la réflexion, mais je veux vraiment éviter cela.

13
Squirrelkiller

Lors de la création d'une instance du contrôleur sous test, assurez-vous d'affecter un HttpContext qui contient les dépendances requises pour que le test soit exercé jusqu'à la fin.

Vous pouvez essayer de vous moquer d'un HttpContext et de le fournir au contrôleur ou simplement utiliser DefaultHttpContext fourni par le 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();

//...

Ce qui précède suppose que vous savez déjà comment se moquer des dépendances du contrôleur comme IAccessor et était destiné à montrer comment fournir les dépendances spécifiques au framework nécessaires au test.

18
Nkosi