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.
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.