coo*_*and 5 c# asp.net unit-testing moq asp.net-core
使用Moq和xUnit进行单元测试的新手.我试图模拟一个SignInManager在控制器构造函数中使用的构建单元测试.我可以为SignInManager构造函数找到的文档说它接受一个UserManager和AuthenticationManager对象:https://msdn.microsoft.com/en-us/library/mt173769(v = vs.108).aspx #M:Microsoft.AspNet.Identity .Owin.SignInManager`2.
当我尝试模拟控制器时,我收到一个错误,说它无法实例化SignInManager和AuthenticationManager类的代理.
错误:
"消息:Castle.DynamicProxy.InvalidProxyConstructorArgumentsException:无法实例化类的代理:Microsoft.AspNetCore.Identity.SignInManager1 [[Models.AppUser ,, Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]].找不到与给定参数匹配的构造函数:Castle.Proxies.UserManager`1Proxy Castle.Proxies.AuthenticationManagerProxy"
单元测试:
public void Can_Send_Password_Reset_Email()
{
//Arrange
//create mock services
Mock<IEmailService> mockEmailService = new Mock<IEmailService>();
Mock<ILessonRepository> mockRepo = new Mock<ILessonRepository>();
Mock<UserManager<AppUser>> mockUsrMgr = GetMockUserManager();
var mockSignInMgr = GetMockSignInManager();
Mock<UserValidator<AppUser>> mockUsrVal = new Mock<UserValidator<AppUser>>();
Mock<PasswordValidator<AppUser>> mockPwdVal = new Mock<PasswordValidator<AppUser>>();
Mock<PasswordHasher<AppUser>> mockPwdHshr = new Mock<PasswordHasher<AppUser>>();
Mock<ForgotPasswordModel> model = new Mock<ForgotPasswordModel>();
model.Object.Email = "joe@example.com";
var user = new AppUser();
var token = mockUsrMgr.Object.GeneratePasswordResetTokenAsync(user).Result;
//create mock temporary data, needed for controller message
Mock<ITempDataDictionary> tempData = new Mock<ITempDataDictionary>();
//create the controller
//ERROR ON THIS LINE
AccountController controller = new AccountController(mockUsrMgr.Object, mockSignInMgr.Object, mockUsrVal.Object, mockPwdVal.Object, mockPwdHshr.Object, mockEmailService.Object)
{
TempData = tempData.Object
};
//Act
//the controller should call the email action method
controller.PasswordResetEmail(model.Object);
//Assert
//verify that the email service method was called one time
mockEmailService.Verify(m => m.PasswordResetMessage(user, "Test Email"), Times.Once());
}
Run Code Online (Sandbox Code Playgroud)
SignInManager模拟函数:
//create a mock SignInManager class
private Mock<SignInManager<AppUser>> GetMockSignInManager()
{
var mockUsrMgr = GetMockUserManager();
var mockAuthMgr = new Mock<AuthenticationManager>();
return new Mock<SignInManager<AppUser>>(mockUsrMgr.Object, mockAuthMgr.Object);
}
Run Code Online (Sandbox Code Playgroud)
GetMockUserManager()其他单元测试中的工作正常,似乎不是问题.
Den*_*uig 11
我就是这样做的,我希望这会对你有所帮助.
public class FakeSignInManager : SignInManager<ApplicationUser>
{
public FakeSignInManager()
: base(new FakeUserManager(),
new Mock<IHttpContextAccessor>().Object,
new Mock<IUserClaimsPrincipalFactory<ApplicationUser>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<ILogger<SignInManager<ApplicationUser>>>().Object,
new Mock<IAuthenticationSchemeProvider>().Object)
{ }
}
public class FakeUserManager : UserManager<ApplicationUser>
{
public FakeUserManager()
: base(new Mock<IUserStore<ApplicationUser>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<ApplicationUser>>().Object,
new IUserValidator<ApplicationUser>[0],
new IPasswordValidator<ApplicationUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<ApplicationUser>>>().Object)
{ }
public override Task<IdentityResult> CreateAsync(ApplicationUser user, string password)
{
return Task.FromResult(IdentityResult.Success);
}
public override Task<IdentityResult> AddToRoleAsync(ApplicationUser user, string role)
{
return Task.FromResult(IdentityResult.Success);
}
public override Task<string> GenerateEmailConfirmationTokenAsync(ApplicationUser user)
{
return Task.FromResult(Guid.NewGuid().ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
huy*_*itw 11
对于 ASP.NET Core 5,可以使用此设置:
var userManagerMock = new Mock<UserManager<User>>(
/* IUserStore<TUser> store */Mock.Of<IUserStore<User>>(),
/* IOptions<IdentityOptions> optionsAccessor */null,
/* IPasswordHasher<TUser> passwordHasher */null,
/* IEnumerable<IUserValidator<TUser>> userValidators */null,
/* IEnumerable<IPasswordValidator<TUser>> passwordValidators */null,
/* ILookupNormalizer keyNormalizer */null,
/* IdentityErrorDescriber errors */null,
/* IServiceProvider services */null,
/* ILogger<UserManager<TUser>> logger */null);
var signInManagerMock = new Mock<SignInManager<User>>(
userManagerMock.Object,
/* IHttpContextAccessor contextAccessor */Mock.Of<IHttpContextAccessor>(),
/* IUserClaimsPrincipalFactory<TUser> claimsFactory */Mock.Of<IUserClaimsPrincipalFactory<User>>(),
/* IOptions<IdentityOptions> optionsAccessor */null,
/* ILogger<SignInManager<TUser>> logger */null,
/* IAuthenticationSchemeProvider schemes */null,
/* IUserConfirmation<TUser> confirmation */null);
Run Code Online (Sandbox Code Playgroud)
在SignInManager拥有不带参数没有构造,所以你必须通过在参数new Mock<SignInManager>(**Params here**)
其中一些参数不能为空,因此它们也必须被模拟:
UserManager<TUser> ==> 第一个参数。IHttpContextAccessor ==> 第二个参数。这里的问题是甚至UserManager没有一个无参数的构造函数,所以你必须用它的参数来模拟
对于Usermanager不应该为空IUserStore<User>的参数 ==> 第一个参数
所以在这里我是如何用最少的代码做的
var _mockUserManager = new Mock<ApiUserManager>(new Mock<IUserStore<ApiUser>>().Object,
null, null, null, null, null, null, null, null);
var _contextAccessor = new Mock<IHttpContextAccessor>();
var _userPrincipalFactory = new Mock<IUserClaimsPrincipalFactory<ApiUser>>();
Mock<ApiSignInManager>mockApiSignInManager = new Mock<ApiSignInManager>(_mockUserManager.Object,
_contextAccessor.Object, _userPrincipalFactory.Object, null, null, null);
Run Code Online (Sandbox Code Playgroud)
此回复的灵感来自GitHub 论坛上的umutesen
您正在查看的文档适用于Microsoft.AspNet.Identity.Owin.SignInManager.
如果您查看错误消息,您会发现 Moq 实际上正在尝试创建 类型的对象Microsoft.AspNetCore.Identity.SignInManager。AspNet注意和之间的区别AspNetCore。
基本上,您正在查看SignInManager旧的基于 Owin 的经典 ASP.NET 身份堆栈中使用的身份堆栈。但你需要查看 ASP.NET Core 版本。如果您查看该类型的文档,您会发现构造函数还有更多依赖项:
public SignInManager(
UserManager<TUser> userManager,
IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<TUser> claimsFactory,
IOptions<Microsoft.AspNetCore.Identity.IdentityOptions> optionsAccessor,
ILogger<Microsoft.AspNetCore.Identity.SignInManager<TUser>> logger,
IAuthenticationSchemeProvider schemes);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3552 次 |
| 最近记录: |