Asp .Net 核心单元测试模拟 UserManager.CreateAsync 和 return 身份结果
Asp .Net Core Unit Test Mock UserManager.CreateAsync and return Identity Result
致力于 .Net Core 项目并创建以下服务以跨页面共享常用方法。
namespace MyApp.Tests.Services
{
public class UserServiceTest
{
[Fact]
public async Task CreateUser_ShouldCreateUser()
{
var user = new UserResponse
{
Id = "111",
Email = "john@email.com",
FirstName = "John",
LastName = "Doe",
CompanyName = "SomeCompany",
PhoneNumber = "9123456789"
};
var appUser = new ApplicationUser
{
UserName = user.Email,
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
CompanyName = user.CompanyName,
PhoneNumber = user.PhoneNumber
};
var logger = Mock.Of<ILogger<UserService>>();
var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
mockUserStore
.Setup(x => x.CreateAsync(appUser, CancellationToken.None))
.ReturnsAsync(IdentityResult.Success).Verifiable();
// Tried this one as well but still getting null instead of IdentityResult
// mockUserStore
// .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
// .ReturnsAsync(new IdentityResultMock(true));
var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
var _userService = new UserService(userManager, logger);
var result = await _userService.CreateUserInApp(user);
Assert.True(result.Succeeded);
}
}
public class IdentityResultMock : IdentityResult
{
public IdentityResultMock(bool succeeded) {
base.Succeeded = succeeded;
}
}
}
还为此服务编写了单元测试用例,如下所示以测试 UserService
namespace MyApp.Tests.Services
{
public class UserServiceTest
{
[Fact]
public async Task CreateUser_ShouldCreateUser()
{
var user = new UserResponse
{
Id = "111",
Email = "john@email.com",
FirstName = "John",
LastName = "Doe",
CompanyName = "SomeCompany",
PhoneNumber = "9123456789"
};
var appUser = new ApplicationUser
{
UserName = user.Email,
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
CompanyName = user.CompanyName,
PhoneNumber = user.PhoneNumber
};
var logger = Mock.Of<ILogger<UserService>>();
var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
mockUserStore
.Setup(x => x.CreateAsync(appUser, CancellationToken.None))
.ReturnsAsync(IdentityResult.Success).Verifiable(); ;
var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
var _userService = new UserService(userManager, logger);
var result = await _userService.CreateUserInApp(user);
Assert.True(result.Succeeded);
}
}
}
同时 运行 在
测试用户服务
var createResult = await _userManager.CreateAsync(appUser);
createResult 由于此测试用例失败并出现空引用异常,我得到空值。
如果我可以 return 来自模拟 CreateAsync 设置的 IdentityResult 那么它将通过但不确定我在做什么错。
也无法创建 IdentityResult 的对象,因为 'Succeeded' 受保护并且无法显式分配值。
请帮忙。谢谢 :)
我们需要看看构造函数内部发生了什么:
var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
但不是真的。如果您在这里测试 UserService
,那么您应该模拟的是 UserManager
而不是它的内部依赖性 IUserStore
.
这是为什么?因为 UserManager
的内部结构可能会发生变化,所以您必须同时更改 UserManager
测试和 UserService
测试。
像创建 IUserStore
一样模拟 UserManager
的创建,您会发现它是 UserStore 中的其他依赖项或完全超出单元测试范围的某个地方。
编辑 1
我想我解决了你的问题:
mockUserStore
.Setup(x => x.CreateAsync(appUser, CancellationToken.None))
.ReturnsAsync(IdentityResult.Success).Verifiable();
和
的调用
var result = await _userService.CreateUserInApp(user);
User 对象和 appUser 对象不同,因此模拟框架没有 return 预期值。
为确保这是问题所在,请尝试使用
进行模拟
mockUserStore
.Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(IdentityResult.Success).Verifiable();
致力于 .Net Core 项目并创建以下服务以跨页面共享常用方法。
namespace MyApp.Tests.Services
{
public class UserServiceTest
{
[Fact]
public async Task CreateUser_ShouldCreateUser()
{
var user = new UserResponse
{
Id = "111",
Email = "john@email.com",
FirstName = "John",
LastName = "Doe",
CompanyName = "SomeCompany",
PhoneNumber = "9123456789"
};
var appUser = new ApplicationUser
{
UserName = user.Email,
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
CompanyName = user.CompanyName,
PhoneNumber = user.PhoneNumber
};
var logger = Mock.Of<ILogger<UserService>>();
var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
mockUserStore
.Setup(x => x.CreateAsync(appUser, CancellationToken.None))
.ReturnsAsync(IdentityResult.Success).Verifiable();
// Tried this one as well but still getting null instead of IdentityResult
// mockUserStore
// .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
// .ReturnsAsync(new IdentityResultMock(true));
var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
var _userService = new UserService(userManager, logger);
var result = await _userService.CreateUserInApp(user);
Assert.True(result.Succeeded);
}
}
public class IdentityResultMock : IdentityResult
{
public IdentityResultMock(bool succeeded) {
base.Succeeded = succeeded;
}
}
}
还为此服务编写了单元测试用例,如下所示以测试 UserService
namespace MyApp.Tests.Services
{
public class UserServiceTest
{
[Fact]
public async Task CreateUser_ShouldCreateUser()
{
var user = new UserResponse
{
Id = "111",
Email = "john@email.com",
FirstName = "John",
LastName = "Doe",
CompanyName = "SomeCompany",
PhoneNumber = "9123456789"
};
var appUser = new ApplicationUser
{
UserName = user.Email,
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
CompanyName = user.CompanyName,
PhoneNumber = user.PhoneNumber
};
var logger = Mock.Of<ILogger<UserService>>();
var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
mockUserStore
.Setup(x => x.CreateAsync(appUser, CancellationToken.None))
.ReturnsAsync(IdentityResult.Success).Verifiable(); ;
var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
var _userService = new UserService(userManager, logger);
var result = await _userService.CreateUserInApp(user);
Assert.True(result.Succeeded);
}
}
}
同时 运行 在
测试用户服务var createResult = await _userManager.CreateAsync(appUser);
createResult 由于此测试用例失败并出现空引用异常,我得到空值。 如果我可以 return 来自模拟 CreateAsync 设置的 IdentityResult 那么它将通过但不确定我在做什么错。 也无法创建 IdentityResult 的对象,因为 'Succeeded' 受保护并且无法显式分配值。 请帮忙。谢谢 :)
我们需要看看构造函数内部发生了什么:
var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
但不是真的。如果您在这里测试 UserService
,那么您应该模拟的是 UserManager
而不是它的内部依赖性 IUserStore
.
这是为什么?因为 UserManager
的内部结构可能会发生变化,所以您必须同时更改 UserManager
测试和 UserService
测试。
像创建 IUserStore
一样模拟 UserManager
的创建,您会发现它是 UserStore 中的其他依赖项或完全超出单元测试范围的某个地方。
编辑 1
我想我解决了你的问题:
mockUserStore
.Setup(x => x.CreateAsync(appUser, CancellationToken.None))
.ReturnsAsync(IdentityResult.Success).Verifiable();
和
的调用var result = await _userService.CreateUserInApp(user);
User 对象和 appUser 对象不同,因此模拟框架没有 return 预期值。
为确保这是问题所在,请尝试使用
进行模拟mockUserStore
.Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(IdentityResult.Success).Verifiable();