2009-12-30 47 views
14

Có cách nào để giả lập/giả mạo đối tượng phiên trong biểu mẫu Web ASP.Net khi tạo các kiểm tra đơn vị không?Làm cách nào để giả lập/giả mạo đối tượng phiên trong biểu mẫu Web ASP.Net?

Tôi hiện đang lưu trữ chi tiết người dùng trong biến phiên được truy cập bởi logic nghiệp vụ của tôi.

Khi thử nghiệm logic nghiệp vụ của tôi riêng biệt, phiên không có sẵn. Điều này dường như chỉ ra một thiết kế xấu (mặc dù tôi không chắc chắn). Lớp logic kinh doanh có nên truy cập vào các biến phiên ở nơi đầu tiên không?

Nếu có, thì tôi sẽ chuyển đổi chi tiết người dùng bằng một đối tượng giả để thử nghiệm như thế nào?

+0

Cũng xem câu trả lời của tôi về vấn đề này - http://stackoverflow.com/a/8487847/232593 –

Trả lời

9

Trong ASP.NET, bạn không thể tạo Test Double của HttpSessionState vì nó là sealed. Có, đây là thiết kế xấu trên một phần của các nhà thiết kế ban đầu của ASP.NET, nhưng không có nhiều việc phải làm.

Đây là một trong nhiều lý do tại sao TDD'ers và các nhà thực hành SOLID khác phần lớn từ bỏ ASP.NET ủng hộ ASP.NET MVC và các khung công tác có thể kiểm thử khác. Trong ASP.NET MVC, phiên HTTP được mô hình hóa bởi lớp HttpSessionStateBase trừu tượng.

Bạn có thể thực hiện một cách tiếp cận tương tự và cho phép đối tượng của bạn làm việc trên một phiên trừu tượng và sau đó bọc lớp HttpSessionState thực khi bạn đang chạy trong môi trường ASP.NET. Tùy thuộc vào hoàn cảnh, bạn thậm chí có thể tái sử dụng các loại từ System.Web.Abstractions, nhưng nếu không, bạn có thể định nghĩa của riêng bạn.

Trong mọi trường hợp, logic nghiệp vụ của bạn là Mô hình miền và nó phải được mô hình độc lập với bất kỳ công nghệ thời gian chạy cụ thể nào, vì vậy tôi sẽ nói rằng không nên truy cập đối tượng phiên.

Nếu bạn hoàn toàn cần phải sử dụng thử nghiệm đôi cho tets đơn vị liên quan đến HttpSessionState, điều này vẫn còn có thể với một số mocks động xâm lấn, chẳng hạn như TypeMock hay Moles, mặc dù điều này mang nhiều nhược điểm cũng (xem this comparison of dynamic mocks).

1

Bản năng của bạn là chính xác --- bạn không nên truy cập các phần của khung ASP.NET từ logic nghiệp vụ của bạn. Điều này sẽ bao gồm Phiên.

Để trả lời câu hỏi đầu tiên, bạn có thể giả lập các lớp tĩnh sử dụng sản phẩm như Typemock Isolator, nhưng bạn sẽ tốt hơn nếu bạn refactor mã của bạn để bọc truy cập vào phiên trong một giao diện (tức là, IHttpSession.) Sau đó bạn có thể giả lập IHttpSession.

0

Một cách tiếp cận là chuyển biểu thức lambda vào mã của bạn, lấy một chuỗi (hoặc một số đối tượng khác) làm đầu vào và sử dụng nó để đặt đối tượng Phiên hoặc vùng chứa thử nghiệm.

Tuy nhiên, như những người khác đã nói, bạn nên chuyển quyền truy cập vào đối tượng Phiên trong BLL của mình.

1

Trong biểu mẫu web Asp.Net, bạn không thể thoát khỏi thực tế rằng việc nhập khuôn khổ vào mã của bạn đến từ các trang aspx. Tôi đồng ý rằng lớp kinh doanh của bạn không nên chạm vào các thành phần cụ thể asp.net trực tiếp nhưng bạn phải có một container lưu trữ của mô hình và phiên trong asp.net là một khu vực tốt. Do đó, một cách tiếp cận có thể là tạo ISessionManager cho mục đích tương tác bên trong lớp nghiệp vụ của bạn. Sau đó, thực hiện kiểu cụ thể bằng cách sử dụng HttpSessionState ... btw, một thủ thuật tốt là sử dụng HttpContext.Current.Session để thực hiện các trình truy cập/getters ra khỏi HttpSessionState. Thách thức tiếp theo của bạn sẽ là cách kết nối tất cả lại với nhau.

25

Bạn có thể thực hiện với 4 dòng mã cơ bản. Mặc dù điều này không nói đến nhận xét trước đó về phiên di chuyển ra khỏi lớp logic nghiệp vụ của bạn, đôi khi bạn có thể cần thực hiện việc này nếu bạn đang làm việc với mã cũ được kết hợp nhiều với phiên (kịch bản của tôi).

Các không gian tên:

using System.Web; 
using System.IO; 
using System.Web.Hosting; 
using System.Web.SessionState; 

Mã:

HttpWorkerRequest _wr = new SimpleWorkerRequest(
    "/dummyWorkerRequest", @"c:\inetpub\wwwroot\dummy", 
    "default.aspx", null, new StringWriter()); 

HttpContext.Current = new HttpContext(_wr); 

var sessionContainer = new HttpSessionStateContainer(
    "id", new SessionStateItemCollection(), 
    new HttpStaticObjectsCollection(), 10, true, 
    HttpCookieMode.AutoDetect, SessionStateMode.InProc, false); 

SessionStateUtility.AddHttpSessionStateToContext(
    HttpContext.Current, sessionContainer); 

Sau đó bạn có thể tham khảo phiên mà không nhận được một lỗi NullReferenceException:

HttpContext.Current.Session.Add("mySessionKey", 1); 

Đây là một sự kết hợp của mã Tôi đã biên soạn từ các bài viết dưới đây:

+0

Tuyệt vời, cảm ơn. –

+0

Cảm ơn, Công việc tốt – Manish

+0

Tôi nhận được ngoại lệ ViewEngine khi gọi phương thức chỉ mục từ lớp kiểm tra đơn vị. Có giải pháp nào cho cùng không? – Manish

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