149 votes

Mock HttpContext pour les tests unitaires d'un contrôleur MVC .NET core ?

J'ai une fonction dans un contrôleur que je teste en unité et qui attend des valeurs dans l'en-tête de la requête http. Je ne peux pas initialiser le HttpContext car il est en lecture seule.

Ma fonction de contrôleur attend une valeur d'en-tête de requête http pour "device-id".

[TestMethod]
public void TestValuesController()
{
    ValuesController controller = new ValuesController();

    //not valid controller.HttpContext is readonly
    //controller.HttpContext = new DefaultHttpContext(); 

    var result = controller.Get();
    Assert.AreEqual(result.Count(), 2);
}

Existe-t-il un moyen simple de le faire sans utiliser une bibliothèque tierce ?

2 votes

Ne fais pas ça. utiliser HttpContext ? L'intérêt d'utiliser des contrôleurs est que les données passent par les paramètres du contrôleur. Si votre contrôleur utilise le HttpContext pour lire les données comme s'il s'agissait d'une page WebForms, vous avez un problème.

1 votes

@PanagiotisKanavos La valeur de l'en-tête est un élément d'information indiquant de quel appareil mobile provient l'appel. Cette information est nécessaire pour récupérer les données correctes. L'ID de l'appareil est dans l'en-tête parce que l'ID est nécessaire pour l'authentification, qui est gérée par un filtre d'action personnalisé. Je pourrais transmettre l'ID de l'appareil en tant que paramètre de route, mais ce serait redondant.

0 votes

Vérifiez FromHeaderAttribute mais aussi le duplicata. HttpContext est injectable par la configuration maintenant.

319voto

James Wierzba Points 5885

J'ai pu initialiser le httpcontext et le header de cette manière :

[TestMethod]
public void TestValuesController()
{
    ValuesController controller = new ValuesController();
    controller.ControllerContext = new ControllerContext();
    controller.ControllerContext.HttpContext = new DefaultHttpContext();
    controller.ControllerContext.HttpContext.Request.Headers["device-id"] = "20317";
    var result = controller.Get();
    //the controller correctly receives the http header key value pair device-id:20317
    ...
}

1 votes

Un exemple parfait

23voto

GlennSills Points 940

Plutôt que de simuler le HTTPContext, il est probablement préférable de transformer l'en-tête en un paramètre de la méthode. Par exemple, dans le contrôleur au bas de cette réponse, le paramètre id est défini sur l'en-tête de valeur avec un nom égal à "device-id"... Le test unitaire devient alors

[TestMethod]
public void TestValuesController()
{
    ValuesController controller = new ValuesController();
    var result = controller.GetHeaderValue("27");
    Assert.AreEqual(result, "27");
}

Pendant que vous peut se moque du HttpContext, à mon avis c'est quelque chose qui devrait être évité à moins que vous n'ayez pas le choix. La documentation relative à l'attribut FromHeaderAttribute peut être consultée ici. Classe FromHeaderAttribute .

public class ValuesController: Controller
{
    public string GetHeaderValue([FromHeader(Name = "device-id")] string id)
    {
        return id;
    }
}

1 votes

Dans mon cas, IIRC, il était nécessaire de l'inclure dans l'en-tête http parce que la même valeur devait être évaluée dans un composant middleware .net core.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X