BWG*_*BWG 9 c# unit-testing moq asp.net-core asp.net-core-identity
我在研究如何测试以及测试什么方面遇到了问题.
我有一个控制器注入UserManager
并调用该CreateAsync
方法来创建一个新用户.
我不想测试Identity用户管理器,因为它已经经过了彻底的测试.我想做的是测试控制器是否运行正确的路径(在我的情况下,有3条路径,发回响应模型状态错误,身份响应错误或简单字符串)
我是否应该尝试创建用户管理器的模拟以创建我的测试(我不确定如何将用户管理器设置为模拟依赖项)其次,如何设置条件以验证控制器是否采用了给定的路径.
我正在使用xUnit和Moq.
[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);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的单元测试中,我有以下内容来测试一个快乐的路径场景
[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);
}
Run Code Online (Sandbox Code Playgroud)
在sut.RegisterNewUser(输入)中的"输入"; 指的是一个辅助类,它构造了控制器动作所需的视图模型:
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
};
}
}
Run Code Online (Sandbox Code Playgroud)
我的目标是通过测试强制3个条件:
使用返回json对象的抽象类来处理错误HttpResponseMessage
.控制器的基类只是构造一个for返回.
基本上我想通过强制测试降低模型状态错误路径,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);
}
Run Code Online (Sandbox Code Playgroud)
对快乐路径场景和测试方法的审查表明,无需设置,因为测试UserStore
将直接覆盖用户管理器虚拟成员。
请注意,测试也已设为异步。
- 创建有效的视图模型并返回成功消息
[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);
}
Run Code Online (Sandbox Code Playgroud)
- 创建一个有效的视图模型,但返回一个 IdentityResponse 错误(例如,用户存在)并进行转换
为此,您只需设置模拟以返回有错误的结果。
[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);
}
Run Code Online (Sandbox Code Playgroud)
而对于
- 创建无效的视图模型并返回 Modelstate 错误
您只需设置控制器的模型状态使其无效即可。
[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);
}
Run Code Online (Sandbox Code Playgroud)
FluentAssertions用于执行所有断言。您可以轻松使用Assert.*
API。
这应该足以让您解决上述问题。
归档时间: |
|
查看次数: |
1774 次 |
最近记录: |