gpt4 book ai didi

c# - Asp.net Core Identity 单元测试 Controller 操作

转载 作者:太空狗 更新时间:2023-10-29 17:57:51 25 4
gpt4 key购买 nike

我在确定如何测试以及测试什么方面遇到了问题。

我有一个注入(inject) UserManager 并调用 CreateAsync 方法来创建新用户的 Controller 。

我不想测试身份用户管理器,因为它显然已经过全面测试。我想做的是测试 Controller 是否通过正确的路径运行(在我的例子中,有 3 条路径,发送回模型状态错误、身份响应错误或简单字符串的响应)

我是否应该尝试创建用户管理器的模拟以创建我的测试(我不确定如何将用户管理器设置为模拟依赖项)其次,如何设置条件来验证 Controller 是否已采用给定路径。

我正在使用 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);
}
}

在我的单元测试中,我有以下内容来测试快乐路径场景

    [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 = "user@test.com" };

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);

}

其中“输入”在 sut.RegisterNewUser(input);指的是构造 Controller 操作所需的 View 模型的辅助类:

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 = "user@test.com";
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
};
}
}

我的目标是通过测试强制满足 3 个条件:

  1. 创建有效的 View 模型并返回成功消息
  2. 创建一个有效的 View 模型但返回一个 IdentityResponse 错误(例如,用户存在),该错误被转换为
  3. 创建无效的 View 模型并返回模型状态错误

使用返回 json 对象的抽象类处理错误 Controller 的基类只是构造一个用于返回的 HttpResponseMessage

基本上,我想检查是否调用了正确的错误响应类,方法是在模型状态错误路径、identityresult.errors 路径下强制测试,并且可以实现快乐路径。

然后我的计划是单独测试错误响应类。

希望这些足够详细。

最佳答案

被测方法应该是异步的,而不是使用阻塞调用即 .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);
}

对 Happy Path 场景和测试方法的回顾表明,无需设置 UserStore,因为测试将直接覆盖用户管理器虚拟成员。

请注意,测试也已设为异步。

  1. Create a valid viewmodel and return a success message
[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. Create a valid viewmodel but returns a IdentityResponse error (eg. user exists) which gets converted

为此,您只需设置模拟以返回错误的结果。

[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);
}

对于

  1. Create an invalid viewmodel and returns Modelstate errors

只需要设置controller的model state使其无效即可。

[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 用于执行所有断言。您可以同样轻松地使用 Assert.* API。

这应该足以帮助您解决上述问题。

关于c# - Asp.net Core Identity 单元测试 Controller 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47348175/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com