Mock HttpContext để kiểm tra đơn vị một bộ điều khiển MVC lõi .NET?


95

Tôi có một chức năng trong bộ điều khiển mà tôi đang kiểm tra đơn vị mong đợi các giá trị trong tiêu đề của yêu cầu http. Tôi không thể khởi tạo HttpContext vì nó chỉ đọc.

Hàm bộ điều khiển của tôi yêu cầu giá trị tiêu đề yêu cầu http cho "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);
}

Có cách nào dễ dàng để thực hiện việc này mà không cần sử dụng thư viện của bên thứ ba không?


1
Không sử dụng HttpContext? Toàn bộ điểm của việc sử dụng bộ điều khiển là dữ liệu đến thông qua các tham số của bộ điều khiển. Nếu bộ điều khiển của bạn sử dụng HttpContext để đọc dữ liệu như thể nó là một trang WebForms, thì bạn đã gặp sự cố.
Panagiotis Kanavos,

@PanagiotisKanavos Giá trị trong tiêu đề là một phần thông tin cho biết cuộc gọi đến từ thiết bị di động nào. Điều này là cần thiết để truy xuất dữ liệu chính xác. ID thiết bị nằm trong tiêu đề vì ID cần thiết để xác thực, được xử lý bởi bộ lọc hành động tùy chỉnh. Tôi có thể có thể vượt qua các thiết bị ID như một tham số tuyến đường nhưng nó sẽ là thừa
James Wierzba

Kiểm tra FromHeaderAttribute nhưng cũng kiểm tra bản sao. HttpContext hiện có thể được đưa vào thông qua cấu hình
Panagiotis Kanavos

1
Tôi khuyên bạn nên chỉnh sửa câu hỏi của mình để chỉ định chính xác những gì bạn muốn (truy cập vào các trường tiêu đề để xác định thiết bị di động). Tài liệu ASP.NET dường như đang trải qua một giai đoạn .... "quá độ" để nói một cách tử tế, với các trang tài liệu bị thiếu. Kiểm tra câu hỏi này gần như giống hệt nhau mà hỏi làm thế nào để các thiết bị di động tuyến đường
Panagiotis Kanavos

Câu trả lời:


227

Tôi đã có thể khởi tạo httpcontext và tiêu đề theo cách này:

[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

Thay vì chế nhạo HTTPContext, có lẽ nên ánh xạ tiêu đề thành một tham số trên phương thức. Ví dụ: trong bộ điều khiển ở cuối câu trả lời này, idtham số được đặt thành tiêu đề giá trị có tên bằng "device-id" ... Kiểm tra đơn vị sau đó trở thành

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

Mặc dù bạn có thể chế nhạo HttpContext, nhưng theo ý kiến ​​của tôi, đó là điều nên tránh trừ khi bạn không có lựa chọn nào khác. Tài liệu cho FromHeaderAttribute có thể được tìm thấy tại đây FromHeaderAttribute Class .

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

1
Trong trường hợp của tôi, IIRC, nó là một yêu cầu để bao gồm nó trong http tiêu đề vì cùng một giá trị cần được đánh giá trong một thành phần cốt lõi .net middleware
James Wierzba
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.