12/08/2018, 17:09

ASP.NET MVC Tip #12 – Giả mạo Controller Context (1)

Trong mẹo này, tôi sẽ giới thiệu cho các bạn cách kiểm tra bản chất của ASP.NET khi xây dựng các bài unit tests cho một ứng dụng ASP.NET MVC. Tôi chỉ cho bạn cách tạo một bộ đối tượng giả tạo tiêu chuẩn cho phép giả mạo người dùng hiện tại, vai trò người dùng hiện tại, các tham số yêu cầu, session ...

Trong mẹo này, tôi sẽ giới thiệu cho các bạn cách kiểm tra bản chất của ASP.NET khi xây dựng các bài unit tests cho một ứng dụng ASP.NET MVC. Tôi chỉ cho bạn cách tạo một bộ đối tượng giả tạo tiêu chuẩn cho phép giả mạo người dùng hiện tại, vai trò người dùng hiện tại, các tham số yêu cầu, session state và cookie.

Một ứng dụng ASP.NET MVC có thể kiểm chứng được nhiều hơn một ứng dụng ASP.NET Web Forms. Mỗi tính năng của ASP.NET MVC đều được thiết kế với tính testability. Tuy nhiên, vẫn còn một số khía cạnh của một ứng dụng ASP.NET MVC rất khó để kiểm tra. Cụ thể, bạn có thể khám phá ra rằng việc kiểm tra các kiến ​​thức ASP.NET vẫn còn thách thức trong một ứng dụng ASP.NET MVC.

Có ý gì trong một ASP.NET nội tại? Tôi đang đề cập đến các đối tượng mà thò ra của HttpContext. Những đối tượng này:

· Request.Forms - Bộ scác thông số được post lên một trang.

· Request.QueryString - Bộ các tham số chuỗi truy vấn được chuyển đến một trang.

· Người dùng - Người dùng hiện tại đang yêu cầu trang.

· Request.Cookies - Các cookie trình duyệt được chuyển đến một trang.

· Session - đối tượng session state.

Hãy tưởng tượng, ví dụ, bạn muốn kiểm tra xem hành động của một controller cụ thể, có thực sự đã thêm một mục cụ thể vào session state hay không. Bạn có thể tạo một unit test như sau:

VB Version

<TestMethod()> _
Public Sub TestSessionState()
  ' Arrange
  Dim controller = New HomeController()
 
  ' Act
  Dim result = TryCast(controller.TestSession(), ViewResult)
 
  ' Assert
  Assert.AreEqual("wow!", controller.HttpContext.Session("item1"))
End Sub

C# Version

[TestMethod]
public void TestSessionState()
{
    // Arrange
    var controller = new HomeController();
 
    // Act
    var result = controller.TestSession() as ViewResult;
 
    // Assert
    Assert.AreEqual("wow!", controller.HttpContext.Session["item1"]);
}

Kiểm tra này kiểm tra xem một controller action có tên TestSession() sẽ thêm một mục mới vào session state. Câu cuối cùng trong bài kiểm tra có chứa khẳng định rằng có một mục session state có tên item1 với giá trị "wow!".

Bạn có thể làm thử nghiệm này với controller action sau đây:

VB Version

Public Function TestSession() As ViewResult
    Session("item1") = "wow!"
    Return View()
End Function

C# Version

public ViewResult TestSession()
{
    Session["item1"] = "wow!";
    return View();
}

Hành động điều khiển này thêm một mục mới vào session state với giá trị mong đợi.

Thật không may, nếu bạn chạy unit test, bài kiểm tra sẽ thất bại. Thử nghiệm sẽ thất bại với NullReferenceException. Vấn đề là session state không tồn tại trong context của unit test. Trong thực tế, không có bản chất ASP.NET tồn tại trong một method thử nghiệm. Điều này có nghĩa là bạn không thể kiểm tra cookie, các tham số form, các tham số chuỗi truy vấn, hoặc nhận dạng người dùng hoặc vai trò của người dùng.

Mocking so với Stubbing

Nếu bạn cần phải viết một unit test sử dụng ASP.NET intrinsics thì bạn phải thực hiện một sự lựa chọn. Hai lựa chọn của bạn là sử dụng một Mock Object Framework hoặc sử dụng một bộ các lớp giả mạo.

Một lựa chọn là để mô phỏng ASP.NET intrinsics bằng cách sử dụng một Mock Object Framework như Moq, Typemock Isolator, hoặc Rhino Mocks. Bạn có thể sử dụng bất kỳ một trong những frameworks này để tạo ra các đối tượng giả vờ là ASP.NET intrinsics thông thường. Nếu bạn muốn tìm hiểu thêm, tôi đã viết các bài viết blog trên cả ba trong số Mock Object Frameworks này:

http://weblogs.asp.net/stephenwalther/archive/2008/06/11/tdd-introduction-to-moq.aspx

http://weblogs.asp.net/stephenwalther/archive/2008/03/22/tdd-introduction-to-rhino-mocks.aspx

http://weblogs.asp.net/stephenwalther/archive/2008/03/16/tdd-introduction-to-typemock-isolator.aspx

Tùy chọn khác là xây dựng một tập hợp các lớp học mà bạn có thể sử dụng để mô phỏng nội suy ASP.NET. Bạn có thể tạo tập hợp các lớp này một lần và sử dụng bộ các lớp trong tất cả các dự án ASP.NET MVC trong tương lai của bạn.

Trong mẹo này, tôi sẽ áp dụng cách tiếp cận thứ hai. Tôi sẽ cho bạn thấy làm thế nào bạn có thể dễ dàng kiểm tra ASP.NET intrinsics mà không cần sử dụng một Mock Object Framework bằng cách tạo ra một bộ tiêu chuẩn giả mạo cho ASP.NET intrinsics.

Tạo một Bối cảnh Controller giả

Ở cuối của mẹo này, bạn có thể nhấp vào liên kết tải về để tải các lớp giả mạo. Tôi tạo ra một tập hợp giả mạo ASP.NET intrinsics với các tên sau:

· FakeControllerContext

· FakeHttpContext

· FakeHttpRequest

· FakeHttpSessionState

· FakeIdentity

· FakePrincipal

Bạn có thể sử dụng các giả mạo này bằng cách tạo một thể hiện mới của FakeControllerContext và gán nó cho thuộc tính ControllerContext của controller’ trong một unit test. Ví dụ: đây là cách bạn có thể giả mạo một người dùng cụ thể trong một unit test bằng cách lợi dụng lớp FakeControllerContext:

VB.NET Version

Dim controller = New HomeController()
controller.ControllerContext = New FakeControllerContext(controller, "Stephen")

C# Version

var controller = new HomeController();
controller.ControllerContext = new FakeControllerContext(controller, "Stephen");

Sau khi bạn gán FakeControllerContext cho controller, controller sẽ sử dụng context đó cho phần còn lại của unit test.

Nguồn: https://weblogs.asp.net/stephenwalther/asp-net-mvc-tip-12-faking-the-controller-context

0