2010-03-09 32 views
24

Tôi đã trải qua quá trình làm sạch mã bộ điều khiển của mình để làm cho mỗi hành động có thể kiểm chứng được. Nói chung, điều này không quá khó khăn - nơi chúng tôi có cơ hội sử dụng một đối tượng cố định, như nói FormsAuthentication, chúng tôi thường giới thiệu một số dạng trình bao bọc phù hợp và theo cách vui vẻ của chúng tôi.Là HttpContextWrapper tất cả những gì .... hữu ích?

Vì những lý do không đặc biệt quan trọng đối với cuộc trò chuyện này, khi nói đến cách sử dụng HttpContext, chúng tôi quyết định sử dụng lớp HttpContextWrapper mới được tạo ra thay vì phát minh ra một thứ gì đó được phát triển trong nhà. Một điều chúng tôi đã giới thiệu là khả năng trao đổi trong một HttpContextWrapper (như nói, để kiểm tra đơn vị). Điều này đã được hoàn toàn lấy cảm hứng từ cách Oren Eini xử lý kiểm tra đơn vị với DateTimes (see article, một mô hình chúng tôi cũng sử dụng)

public static class FooHttpContext 
{ 
    public static Func<HttpContextWrapper> Current =() 
     => new HttpContextWrapper(HttpContext.Current); 

    public static void Reset() 
    { 
     Current =() => new HttpContextWrapper(HttpContext.Current); 
    } 
} 

Không có gì đặc biệt ưa thích. Và nó hoạt động tốt trong mã điều khiển của chúng tôi. Các kicker đến khi chúng tôi đi để viết bài kiểm tra đơn vị. Chúng tôi đang sử dụng Moq như khuôn khổ chế giễu của chúng tôi, nhưng than ôi

var context = new Mock<HttpContextWrapper>() 

phá vỡ kể từ HttpContextWrapper không có một ctor parameterless. Và những gì nó lấy như một tham số ctor? Một đối tượng HttpContext. Vì vậy, tôi thấy mình đang nắm bắt 22.

Tôi đang sử dụng cách được quy định để tách HttpContext - nhưng tôi không thể giả định giá trị vì đối tượng HttpContext ban đầu đã được niêm phong và do đó khó kiểm tra. Tôi có thể ánh xạ HttpContextBase, mà cả hai đều xuất phát từ - nhưng điều đó không thực sự làm cho tôi những gì tôi sau. Tôi chỉ thiếu điểm ở đâu đó liên quan đến HttpContextWrapper?

Chỉnh sửa để làm rõ ý định

Chúng tôi tìm thấy cách để giải quyết vấn đề - nhưng tôi đoán câu hỏi cuối cùng, chúng tôi đang đi bộ đi với những gì là giá trị HttpContextWrapper mang đến cho bảng? Tôi không nghi ngờ một nơi nào đó hoàn toàn có một a-ha! khoảnh khắc với nó, nhưng nó không đến với tôi. Hầu hết các bài đăng tôi thấy ở đây đều thảo luận về khả năng kiểm thử - nhưng kinh nghiệm của riêng tôi đã khiến tôi tin rằng nó không mang lại nhiều trong bối cảnh đó. Trừ khi chúng tôi làm sai. (Hoàn toàn có thể).

Trả lời

30

Bạn nên sử dụng hình minh hoạ HttpContextBase dễ dàng hơn nhiều để giả lập thay vì HttpContextWrapper.

public static Func<HttpContextBase> Current = 
    () => new HttpContextWrapper(HttpContext.Current); 

Và trong thử nghiệm đơn vị của bạn:

SomeClass.Current = MockHttpContextBase(); // Sorry I don't know the syntax for Moq 
+0

Bạn' hoàn toàn đúng - và những gì chúng tôi cuối cùng đã làm ... nhưng câu hỏi của tôi nhiều hơn tôi đoán là về những gì Wrapper thực sự mang đến bàn - hãy để tôi chỉnh sửa cho rõ ràng. – bakasan

+1

'HttpContextWrapper' không có nghĩa là trừu tượng nhưng thực thi cụ thể' HttpContextBase'. Tôi đoán giá trị của nó là nó ẩn một số phương thức tĩnh và nội bộ của 'HttpContext'. –

+7

'HttpContextWrapper' triển khai' HttpContextBase' (có thể bỏ qua) bằng cách chuyển tiếp các cuộc gọi đến 'HttpContext' ASP.NET-vintage. Đó là một wart để có được xung quanh thực tế là 'HttpContext' không phải là mockable. –

31

bài viết trên blog này giải thích nó khá tốt:

http://splinter.com.au/httpcontext-vs-httpcontextbase-vs-httpcontext

Vấn đề là 'cổ điển' HttpContext không thực hiện HttpContextBase, và không phải là ảo và do đó không thể bị Mocked. HttpContextBase đã được giới thiệu trong 3,5 như là một thay thế mockable. Nhưng vẫn có vấn đề là HttpContext cổ điển không triển khai HttpContextBase.

Vì vậy HttpContextWrapper là một lớp wrapper tiện dụng (hoặc 'kludge') mà thực hiện HttpContextBase, và có thể được sử dụng khi tiêm một 'thực tế' HttpContext sử dụng IOC, thường là với một phương pháp nhà máy như thế này: () => new HttpContextWrapper(HttpContext.Current)

+4

Và bạn sẽ thiết lập đăng ký trong Unity như sau; 'var container = new UnityContainer(); container.RegisterType (new InjectionConstructor (HttpContext.Current)); ' –

Các vấn đề liên quan