2012-03-21 29 views
8

Tôi khá mới đối với thử nghiệm Đơn vị và khái niệm Mô phỏng. Tôi cố gắng để tìm ra cách để viết một trường hợp thử nghiệm tốt cho out-of-the cơ bản hộp mã số đăng ký sử dụng dưới đây:ASP .Net MVC 3: Thao tác kiểm soát đơn vị kiểm tra

[HttpPost] 
public ActionResult Register(RegisterModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // Attempt to register the user 
     MembershipCreateStatus createStatus; 
     Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus); 

     if (createStatus == MembershipCreateStatus.Success) 
     { 
      FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */); 
      return RedirectToAction("Index", "Home"); 
     } 
     else 
     { 
      ModelState.AddModelError("", ErrorCodeToString(createStatus)); 
     } 
    } 

    // If we got this far, something failed, redisplay form 
    return View(model); 
} 

Dưới đây là một số điểm cụ thể mà tôi cần ý kiến ​​của bạn/giúp đỡ:

  1. Tôi không nhất thiết muốn tạo người dùng mới trong cơ sở dữ liệu thành viên ASP .Net.
  2. Dựa trên mô hình được chuyển vào, làm cách nào để tôi thực sự đảm bảo rằng nếu người dùng đã đăng ký thành công hoặc có lỗi trong quy trình.

Trả lời

25

Bạn gặp sự cố với mã của mình. Hành động của bạn phụ thuộc vào phương pháp tĩnh: Membership.CreateUser. Và như bạn biết phương pháp tĩnh là PITAs để kiểm tra đơn vị.

Vì vậy, bạn có thể làm suy yếu các khớp nối bằng cách giới thiệu một mức độ trừu tượng:

public interface IMyService 
{ 
    MembershipCreateStatus CreateUser(string username, string password, string email); 
} 

và sau đó có một số thực hiện mà sẽ sử dụng các nhà cung cấp thành viên hiện tại:

public class MyService: IMyService 
{ 
    public MembershipCreateStatus CreateUser(string username, string password, string email) 
    { 
     MembershipCreateStatus status; 
      Membership.CreateUser(username, password, email, null, null, true, null, out status); 
     return status; 
    } 
} 

và cuối cùng là bộ điều khiển:

public class AccountController : Controller 
{ 
    private readonly IMyService _service; 
    public AccountController(IMyService service) 
    { 
     _service = service; 
    } 

    [HttpPost] 
    public ActionResult Register(RegisterModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      // Attempt to register the user 
      var status = _service.CreateUser(model.UserName, model.Password, model.Email); 
      if (status == MembershipCreateStatus.Success) 
      { 
       FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */); 
       return RedirectToAction("Index", "Home"); 
      } 
      else 
      { 
       ModelState.AddModelError("", ErrorCodeToString(createStatus)); 
      } 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 
} 

OK, bây giờ chúng tôi đã làm suy yếu khớp nối chúng tôi có thể e một khuôn khổ mocking để giả lập dịch vụ trong bài kiểm tra đơn vị và làm cho nó tầm thường.

Ví dụ sử dụng Rhino Mocks bạn có thể tạo các xét nghiệm sau đây để trang trải các trường hợp 2 thất bại:

[TestMethod] 
public void Register_Action_Should_Redisplay_View_If_Model_Is_Invalid()  
{ 
    // arrange 
    var sut = new AccountController(null); 
    var model = new RegisterModel(); 
    sut.ModelState.AddModelError("", "invalid email"); 

    // act 
    var actual = sut.Register(model); 

    // assert 
    Assert.IsInstanceOfType(actual, typeof(ViewResult)); 
    var viewResult = actual as ViewResult; 
    Assert.AreEqual(model, viewResult.Model); 
} 

[TestMethod] 
public void Register_Action_Should_Redisplay_View_And_Add_Model_Error_If_Creation_Fails() 
{ 
    // arrange 
    var service = MockRepository.GenerateStub<IMyService>(); 
    service 
     .Stub(x => x.CreateUser(null, null, null)) 
     .IgnoreArguments() 
     .Return(MembershipCreateStatus.InvalidEmail); 
    var sut = new AccountController(service); 
    var model = new RegisterModel(); 

    // act 
    var actual = sut.Register(model); 

    // assert 
    Assert.IsInstanceOfType(actual, typeof(ViewResult)); 
    var viewResult = actual as ViewResult; 
    Assert.AreEqual(model, viewResult.Model); 
    Assert.IsFalse(sut.ModelState.IsValid); 
} 

Các thử nghiệm cuối cùng là trường hợp thành công. Chúng tôi vẫn gặp vấn đề với nó. Vấn đề là dòng sau:

FormsAuthentication.SetAuthCookie(model.UserName, false); 

Đây là gì? Đó là một cuộc gọi phương thức tĩnh. Vì vậy, chúng tôi tiến hành theo cách tương tự như chúng tôi đã làm với các nhà cung cấp thành viên để làm suy yếu các khớp nối của bộ điều khiển của chúng tôi và hệ thống xác thực mẫu.

+4

+1 cho lượt đi bộ tuyệt vời và dễ theo dõi. – ljubomir

0

Để kiểm tra phương pháp này, bạn có thể làm theo hai cách

  1. Bên trong lớp thử nghiệm tạo ra một lớp mới được thừa kế từ Membership lớp và ghi đè lên các phương pháp CreateUser.
  2. Sử dụng Moq để giả lập lớp học.

Đối với trường hợp đầu tiên, tôi sẽ kiểm tra xem tên người dùng có bằng "GoodUser" hoặc "BadUser" không và tạo MembershipCreateStatus.Success hoặc trạng thái khác.

Thứ hai, tôi sẽ thiết lập hai phương pháp theo cùng một ý tưởng như trong phương pháp khác. Xem ví dụ này link để biết ví dụ