2017-11-17 34 views
5

Tôi gặp sự cố khi tìm hiểu cách thực hiện và thử nghiệm.Hành động của bộ điều khiển kiểm tra đơn vị Asp.net Core Identity

Tôi có bộ điều khiển tiêm UserManager và gọi phương thức CreateAsync để tạo người dùng mới.

Tôi không muốn kiểm tra Trình quản lý người dùng danh tính vì điều này đã được kiểm tra kỹ lưỡng một cách rõ ràng. Những gì tôi muốn làm là kiểm tra xem bộ điều khiển có chạy đúng đường dẫn hay không (trong trường hợp của tôi, có 3 đường dẫn, gửi phản hồi trở lại với lỗi trạng thái mô hình, lỗi phản hồi danh tính hoặc chuỗi đơn giản)

Tôi có nên cố gắng tạo mô hình quản lý người dùng để tạo thử nghiệm của tôi (Tôi không chắc chắn cách thiết lập trình quản lý người dùng làm phụ thuộc giả) Thứ hai, làm cách nào để tôi có thể đặt điều kiện để xác minh rằng trình điều khiển đã thực hiện một đường dẫn nhất định .

Tôi đang sử dụng xUnitMoq.

[Route("api/[controller]")] 
public class MembershipController : BaseApiController 
{ 
    private UserManager<ApplicationUser> _userManager; 

    public MembershipController(UserManager<ApplicationUser> userManager) 
    { 
     _userManager = userManager; 
    } 

    [HttpGet("RegisterNewUser")] 
    public HttpResponseMessage RegisterNewUser([FromBody] NewUserRegistration user) 
    { 
     if (ModelState.IsValid) 
     { 
      ApplicationUser newUser = new ApplicationUser(); 
      newUser.UserName = user.username; 
      newUser.Email = user.password; 
      IdentityResult result = _userManager.CreateAsync(newUser, user.password).Result; 

      if (result.Errors.Count() > 0) 
      { 
       var errors = new IdentityResultErrorResponse().returnResponseErrors(result.Errors); 
       return this.WebApiResponse(errors, HttpStatusCode.BadRequest); 
      } 
     } 
     else 
     { 
      var errors = new ViewModelResultErrorResponse().returnResponseErrors(ModelState); 
      return this.WebApiResponse(errors, HttpStatusCode.BadRequest); 
     } 

     return this.WebApiResponse(
        "We have sent a valifation email to you, please click on the verify email account link.", 
        HttpStatusCode.OK); 
    } 
} 

Trong thử nghiệm đơn vị của tôi, tôi đã phần sau đây để kiểm tra một con đường hạnh phúc kịch bản

[Fact] 
    public void RegisterNewUser_ReturnsHttpStatusOK_WhenValidModelPosted() 
    { 
     var mockStore = new Mock<IUserStore<ApplicationUser>>(); 
     var mockUserManager = new Mock<UserManager<ApplicationUser>>(mockStore.Object, null, null, null, null, null, null, null, null); 

     ApplicationUser testUser = new ApplicationUser { UserName = "[email protected]" }; 

     mockStore.Setup(x => x.CreateAsync(testUser, It.IsAny<CancellationToken>())) 
      .Returns(Task.FromResult(IdentityResult.Success)); 

     mockStore.Setup(x => x.FindByNameAsync(testUser.UserName, It.IsAny<CancellationToken>())) 
        .Returns(Task.FromResult(testUser)); 


     mockUserManager.Setup(x => x.CreateAsync(testUser).Result).Returns(new IdentityResult()); 

     MembershipController sut = new MembershipController(mockUserManager.Object); 
     var input = new NewUserInputBuilder().Build(); 
     sut.RegisterNewUser(input); 

    } 

đâu "đầu vào" trong sut.RegisterNewUser (đầu vào); dùng để chỉ một lớp helper mà xây dựng viewmodel mà hành động điều khiển yêu cầu:

public class NewUserInputBuilder 
{ 
    private string username { get; set; } 
    private string password { get; set; } 
    private string passwordConfirmation { get; set; } 
    private string firstname { get; set; } 
    private string lastname { get; set; } 

    internal NewUserInputBuilder() 
    { 
     this.username = "[email protected]"; 
     this.password = "password"; 
     this.passwordConfirmation = "password"; 
     this.firstname = "user"; 
     this.lastname = "name"; 
    } 

    internal NewUserInputBuilder WithNoUsername() 
    { 
     this.username = ""; 
     return this; 
    } 

    internal NewUserInputBuilder WithMisMatchedPasswordConfirmation() 
    { 
     this.passwordConfirmation = "MismatchedPassword"; 
     return this; 
    } 

    internal NewUserRegistration Build() 
    { 
     return new NewUserRegistration 
     { username = this.username, password = this.password, 
      passwordConfirmation = this.passwordConfirmation, 
      firstname = this.firstname, lastname = this.lastname 
     }; 
    } 
} 

tôi nhằm mục đích ở đây là để buộc 3 điều kiện thông qua các bài kiểm tra:

  1. Tạo một viewmodel hợp lệ và trả về một thông báo thành công
  2. Tạo chế độ xem hợp lệ nhưng trả về lỗi IdentityResponse (ví dụ: người dùng tồn tại) được chuyển đổi thành
  3. Tạo chế độ xem không hợp lệ và trả về Lỗi mô hình

Các lỗi được xử lý bằng cách sử dụng lớp trừu tượng trả về đối tượng json Lớp cơ sở cho bộ điều khiển chỉ đơn giản là xây dựng một HttpResponseMessage để trả về.

Về cơ bản tôi muốn kiểm tra xem lớp phản hồi lỗi chính xác có được gọi bằng cách buộc kiểm tra xuống đường dẫn lỗi mô hình, đường dẫn identresult.errors và đường dẫn hạnh phúc có thể đạt được hay không.

Sau đó, kế hoạch của tôi là kiểm tra các lớp phản hồi lỗi một cách riêng biệt.

Hy vọng rằng đó là đủ chi tiết.

+0

Mặc dù nó sẽ yêu cầu một số tái cấu trúc, hãy xem câu trả lời tôi đã cung cấp ở đây https://stackoverflow.com/questions/41883635/how-to-use-di-with-usermanager-and-userstore/41885293#41885293 . Một vài mẹo nhanh khi nói đến chế giễu. Đừng chế giễu những gì bạn không sở hữu. Các lớp nên phụ thuộc vào trừu tượng và không phụ thuộc. – Nkosi

+0

Cảm ơn câu trả lời của bạn. Tôi vẫn không thực sự chắc chắn về cách kiểm tra mã của tôi mặc dù. Tôi đang tìm kiếm một câu trả lời hoàn chỉnh hơn một chút. –

+0

Vậy thì tôi khuyên bạn nên bắt đầu bằng cách thử một cái gì đó. Nếu bạn gặp khó khăn cho thấy những gì bạn đã thử và sau đó chúng ta có thể thấy nơi chúng tôi có thể giúp đỡ. Dựa trên những gì bạn đã cung cấp cho đến nay nó sẽ là quá rộng cho một câu trả lời * hoàn thành *. Cộng đồng sẽ cố gắng giúp đỡ tốt nhất có thể nhưng không ngờ rằng nó sẽ làm mọi thứ cho bạn. – Nkosi

Trả lời

0

Mehod dưới kiểm tra nên được thực hiện async và không sử dụng chặn cuộc gọi tức là .Result

[HttpGet("RegisterNewUser")] 
public async Task<HttpResponseMessage> RegisterNewUser([FromBody] NewUserRegistration user) { 
    if (ModelState.IsValid) { 
     var newUser = new ApplicationUser() { 
      UserName = user.username, 
      Email = user.password 
     }; 
     var result = await _userManager.CreateAsync(newUser, user.password); 
     if (result.Errors.Count() > 0) { 
      var errors = new IdentityResultErrorResponse().returnResponseErrors(result.Errors); 
      return this.WebApiResponse(errors, HttpStatusCode.BadRequest); 
     } 
    } else { 
     var errors = new ViewModelResultErrorResponse().returnResponseErrors(ModelState); 
     return this.WebApiResponse(errors, HttpStatusCode.BadRequest); 
    } 

    return this.WebApiResponse(
       "We have sent a valifation email to you, please click on the verify email account link.", 
       HttpStatusCode.OK); 
} 

Rà soát con đường kịch bản và phương pháp thử Chúc mừng cho thấy rằng không có nhu cầu thiết lập các UserStore như thử nghiệm sẽ được ghi đè trực tiếp người quản lý người dùng ảo.

Lưu ý rằng thử nghiệm cũng đã được thực hiện không đồng bộ.

  1. Tạo một viewmodel hợp lệ và trả về một thông báo thành công
[Fact] 
public async Task RegisterNewUser_ReturnsHttpStatusOK_WhenValidModelPosted() { 
    //Arrange 
    var mockStore = Mock.Of<IUserStore<ApplicationUser>>(); 
    var mockUserManager = new Mock<UserManager<ApplicationUser>>(mockStore, null, null, null, null, null, null, null, null); 

    mockUserManager 
     .Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>())) 
     .ReturnsAsync(IdentityResult.Success); 

    var sut = new MembershipController(mockUserManager.Object); 
    var input = new NewUserInputBuilder().Build(); 

    //Act 
    var actual = await sut.RegisterNewUser(input); 

    //Assert 
    actual 
     .Should().NotBeNull() 
     .And.Match<HttpResponseMessage>(_ => _.IsSuccessStatusCode == true);   
} 
  1. Tạo một viewmodel hợp lệ nhưng trả về một lỗi IdentityResponse (ví dụ . người dùng tồn tại) được chuyển đổi

Đối với điều này, bạn chỉ cần thiết lập mô hình để trả lại kết quả có lỗi.

[Fact] 
public async Task RegisterNewUser_ReturnsHttpStatusBadRequest_WhenViewModelPosted() { 
    //Arrange 

    //...code removed for brevity 

    mockUserManager 
     .Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>())) 
     .ReturnsAsync(IdentityResult.Failed(new IdentityError { Description = "test"})); 

    //...code removed for brevity 

    //Assert 
    actual 
     .Should().NotBeNull() 
     .And.Match<HttpResponseMessage>(_ => _.StatusCode == HttpStatusCode.BadRequest); 
} 

Và đối với

  1. Tạo một viewmodel không hợp lệ và trả ModelState lỗi

Bạn chỉ cần thiết lập trạng thái mô hình của điều khiển sao cho nó không hợp lệ.

[Fact] 
public async Task RegisterNewUser_ReturnsHttpStatusBadRequest_WhenInvalidModelState() { 
    //Arrange 
    var mockStore = Mock.Of<IUserStore<ApplicationUser>>(); 
    var mockUserManager = new Mock<UserManager<ApplicationUser>>(mockStore, null, null, null, null, null, null, null, null); 

    var sut = new MembershipController(mockUserManager.Object); 
    sut.ModelState.AddModelError("", "invalid data"); 
    var input = new NewUserInputBuilder().Build(); 

    //Act 
    var actual = await sut.RegisterNewUser(input); 

    //Assert 
    actual 
     .Should().NotBeNull() 
     .And.Match<HttpResponseMessage>(_ => _.StatusCode == HttpStatusCode.BadRequest);  
} 

FluentAssertions được sử dụng để làm tất cả những khẳng định. Bạn có thể dễ dàng sử dụng API Assert.*.

Điều này sẽ đủ để giúp bạn thực hiện theo cách của mình với câu hỏi trên.

+0

Tôi gần như bị mất cho các từ. Cảm ơn bạn đã trả lời tuyệt vời nhất, điều này đã thực sự lấp đầy khoảng trống và đã thực sự cải thiện sự hiểu biết của tôi. –

+0

@BenWhite với thử nghiệm đơn vị bạn muốn cô lập điều đang được thử nghiệm. Trong trường hợp có các phụ thuộc bạn muốn có khả năng giả lập các phụ thuộc để các bài kiểm tra có thể được thực hiện để hoàn thành như dự định. Khi bạn đi qua dòng chảy của phương pháp của bạn được thử nghiệm, nó sẽ cho bạn thấy những gì cần phải được thao tác để đạt được kết quả mong muốn. – Nkosi

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