2008-10-06 24 views
44

Tôi đọc một số câu trả lời ở đây: kiểm tra xem và điều khiển, và chế nhạo, nhưng tôi vẫn không thể tìm ra cách kiểm tra bộ điều khiển ASP.NET MVC đọc và đặt giá trị phiên (hoặc bất kỳ biến ngữ cảnh nào khác .) Làm cách nào để cung cấp ngữ cảnh (Phiên) cho các phương pháp thử nghiệm của tôi? Có chế giễu câu trả lời không? Có ai có ví dụ không? Về cơ bản, tôi muốn giả mạo một phiên trước khi tôi gọi phương thức điều khiển và có bộ điều khiển sử dụng phiên đó. Bất kỳ ý tưởng?ASP/NET MVC: Bộ điều khiển thử nghiệm w/Phiên? Mocking?

Trả lời

43

Kiểm tra bài Stephen Walther về Giả mạo bối cảnh Bộ điều khiển:

ASP.NET MVC Tip #12 – Faking the Controller Context

[TestMethod] 
public void TestSessionState() 
{ 
    // Create controller 
    var controller = new HomeController(); 


    // Create fake Controller Context 
    var sessionItems = new SessionStateItemCollection(); 
    sessionItems["item1"] = "wow!"; 
    controller.ControllerContext = new FakeControllerContext(controller, sessionItems); 
    var result = controller.TestSession() as ViewResult; 


    // Assert 
    Assert.AreEqual("wow!", result.ViewData["item1"]); 

    // Assert 
    Assert.AreEqual("cool!", controller.HttpContext.Session["item2"]); 
} 
+3

Tôi phải tìm kiếm url này, vì vậy tại đây là: http://stephenwalther.com/blog/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-context. aspx – blu

+3

Nó có thể không được rõ ràng, nhưng FakeControllerContext là một lớp tùy chỉnh. Bạn có thể thấy mã nguồn ở đây: http://stephenwalther.com/Downloads/Tips/Tip12/Tip12.zip –

+0

Liên kết nguồn ở trên dường như đã chết .. bất kỳ ai cũng có bản sao? – Flores

12

Khuôn khổ ASP.NET MVC không phải là rất thân thiện (hay đúng hơn, đòi hỏi quá nhiều thiết lập để giả lập đúng cách, và gây ra quá nhiều ma sát khi thử nghiệm, IMHO) do nó sử dụng các lớp cơ sở trừu tượng thay vì giao diện. Chúng tôi đã có may mắn viết abstractions cho mỗi yêu cầu và lưu trữ dựa trên phiên. Chúng tôi giữ cho những trừu tượng này rất nhẹ và sau đó các bộ điều khiển của chúng tôi phụ thuộc vào những trừu tượng đó cho lưu trữ theo yêu cầu hoặc mỗi phiên.

Ví dụ: dưới đây là cách chúng tôi quản lý nội dung xác thực biểu mẫu. Chúng tôi có một ISecurityContext:

public interface ISecurityContext 
{ 
    bool IsAuthenticated { get; } 
    IIdentity CurrentIdentity { get; } 
    IPrincipal CurrentUser { get; set; } 
} 

Với một thực hiện cụ thể như:

public class SecurityContext : ISecurityContext 
{ 
    private readonly HttpContext _context; 

    public SecurityContext() 
    { 
     _context = HttpContext.Current; 
    } 

    public bool IsAuthenticated 
    { 
     get { return _context.Request.IsAuthenticated; } 
    } 

    public IIdentity CurrentIdentity 
    { 
     get { return _context.User.Identity; } 
    } 

    public IPrincipal CurrentUser 
    { 
     get { return _context.User; } 
     set { _context.User = value; } 
    } 
} 
2

Scott Hanselman có một bài về cách create a file upload quickapp với MVC và thảo luận moking và đặc biệt đề cập đến "Làm thế nào để thử những điều mà aren 'Mock thân thiện. "

+0

Hanselman để giải cứu ... – Codewerks

5

Tôi thấy chế nhạo là khá dễ dàng. Dưới đây là một ví dụ về chế nhạo httpContextbase (có chứa các yêu cầu, phiên và các đối tượng phản hồi) bằng cách sử dụng moq.

[TestMethod] 
     public void HowTo_CheckSession_With_TennisApp() { 
      var request = new Mock<HttpRequestBase>(); 
      request.Expect(r => r.HttpMethod).Returns("GET");  

      var httpContext = new Mock<HttpContextBase>(); 
      var session = new Mock<HttpSessionStateBase>(); 

      httpContext.Expect(c => c.Request).Returns(request.Object); 
      httpContext.Expect(c => c.Session).Returns(session.Object); 

      session.Expect(c => c.Add("test", "something here"));    

      var playerController = new NewPlayerSignupController(); 
      memberController.ControllerContext = new ControllerContext(new RequestContext(httpContext.Object, new RouteData()), playerController);   

      session.VerifyAll(); // function is trying to add the desired item to the session in the constructor 
      //TODO: Add Assertions 
     } 

Hy vọng điều đó sẽ hữu ích.

+2

Wow, đó là rất nhiều công việc chỉ để thử một phương pháp :) Đây rõ ràng là "quá nhiều thiết lập "mùi, và đó là kết quả của việc sử dụng các lớp cơ sở trừu tượng hơn là các giao diện như các đường nối phụ thuộc. – chadmyers

+1

Chắc chắn, tôi đã thấy một vài dự án mà họ đặt mã thiết lập trong một lớp "trợ giúp" và sử dụng nó hơn và hơn nữa. – Korbin

+0

FYI, nếu kiểm tra của bạn cần thiết lập rất nhiều mà bạn cần một lớp 'helper', bạn sẽ có nỗi đau và ma sát xuống dòng. – chadmyers

8

Với MVC RC 1 các ControllerContext kết thúc tốt đẹp HttpContext và cho thấy nó như là một tài sản. Điều này làm cho việc chế nhạo dễ dàng hơn nhiều. Để giả lập biến phiên với Moq, hãy làm như sau:

var controller = new HomeController(); 
var context = MockRepository.GenerateStub<ControllerContext>(); 
context.Expect(x => x.HttpContext.Session["MyKey"]).Return("MyValue"); 
controller.ControllerContext = context; 

Xem Scott Gu's post để biết thêm chi tiết.

0

Vì HttpContext là tĩnh, tôi sử dụng Typemock Isolator để giả lập nó, Typemock cũng có một tùy chỉnh Add-in được xây dựng cho ASP.NET unit testing được gọi là Ivonna.

2

Tôi đã sử dụng giải pháp sau đây - tạo bộ điều khiển mà tất cả các bộ điều khiển khác của tôi kế thừa từ đó.

public class TestableController : Controller 
{ 

    public new HttpSessionStateBase Session 
    { 
     get 
     { 
      if (session == null) 
      { 
       session = base.Session ?? new CustomSession(); 
      } 
      return session; 
     } 
    } 
    private HttpSessionStateBase session; 

    public class CustomSession : HttpSessionStateBase 
    { 

     private readonly Dictionary<string, object> dictionary; 

     public CustomSession() 
     { 
      dictionary = new Dictionary<string, object>(); 
     } 

     public override object this[string name] 
     { 
      get 
      { 
       if (dictionary.ContainsKey(name)) 
       { 
        return dictionary[name]; 
       } else 
       { 
        return null; 
       } 
      } 
      set 
      { 
       if (!dictionary.ContainsKey(name)) 
       { 
        dictionary.Add(name, value); 
       } 
       else 
       { 
        dictionary[name] = value; 
       } 
      } 
     } 

     //TODO: implement other methods here as needed to forefil the needs of the Session object. the above implementation was fine for my needs. 

    } 

} 

Sau đó sử dụng các mã như sau:

public class MyController : TestableController { } 
Các vấn đề liên quan