Mock HttpContext do testowania jednostkowego kontrolera MVC .NET core?


102

Mam funkcję w kontrolerze, który jest testem jednostkowym, który oczekuje wartości w nagłówku żądania http. Nie mogę zainicjować HttpContext, ponieważ jest on tylko do odczytu.

Funkcja mojego kontrolera oczekuje wartości nagłówka żądania http dla „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);
}

Czy istnieje prosty sposób na zrobienie tego bez korzystania z biblioteki innej firmy?


1
Nie używasz HttpContext? Cały sens korzystania z kontrolerów polega na tym, że dane przechodzą przez parametry kontrolera. Jeśli kontroler używa HttpContext do odczytywania danych tak, jakby była to strona formularzy sieci Web, masz problem.
— Panagiotis Kanavos

@PanagiotisKanavos Wartość w nagłówku to informacja wskazująca, z jakiego urządzenia mobilnego pochodzi połączenie. Jest to konieczne, aby pobrać prawidłowe dane. Identyfikator urządzenia znajduje się w nagłówku, ponieważ jest on potrzebny do uwierzytelnienia, które jest obsługiwane przez niestandardowy filtr akcji. Mógłbym przekazać identyfikator urządzenia jako parametr trasy, ale byłby on zbędny
— James Wierzba

Sprawdź FromHeaderAttribute, ale także sprawdź duplikat. HttpContext można teraz wstrzykiwać poprzez konfigurację
— Panagiotis Kanavos

1
Proponuję edytować swoje pytanie, aby dokładnie określić, czego chcesz (dostęp do pól nagłówka w celu identyfikacji urządzeń mobilnych). Wydaje się, że dokumentacja ASP.NET przechodzi… okres „przejściowy”, delikatnie mówiąc, z brakującymi stronami z dokumentacją. Sprawdź to prawie identyczne pytanie, które pyta, jak
— trasować

Odpowiedzi:


233

Udało mi się zainicjować httpcontext i nagłówek w ten sposób:

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

21

Zamiast wyszydzać HTTPContext, prawdopodobnie lepszym pomysłem jest zamapowanie nagłówka na parametr metody. Na przykład w kontrolerze na dole tej odpowiedzi idparametr jest ustawiony na nagłówek wartości o nazwie równej „identyfikator urządzenia” ... Test jednostkowy staje się wtedy

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

Podczas można drwić HttpContext, moim zdaniem to jest coś, co powinno się unikać, chyba że nie masz wyboru. Dokumentację dotyczącą FromHeaderAttribute można znaleźć tutaj FromHeaderAttribute Class .

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

1
W moim przypadku, IIRC, wymagane było umieszczenie go w nagłówku http, ponieważ ta sama wartość musiała zostać oszacowana w komponencie pośredniczącym .net core
— James Wierzba
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.