C# 如何对ASP.NETCore3.0和x2B进行单元测试;需要UserManager的Razor页面处理程序<;TUser>;和签名管理员<;TUser>;?
我试图简单地测试Register.cshtml.csC# 如何对ASP.NETCore3.0和x2B进行单元测试;需要UserManager的Razor页面处理程序<;TUser>;和签名管理员<;TUser>;?,c#,unit-testing,asp.net-core,razor-pages,C#,Unit Testing,Asp.net Core,Razor Pages,我试图简单地测试Register.cshtml.csOnGet()方法。页面模型需要一个UserManager和一个SignInManager。我需要模拟需要这些类的SignInManager.IsSignedIn(ClaimsPrincipal用户)方法。问题是ASP.NET核心中这些类的构造函数比以前ASP.NET版本的大多数解决方案文档要复杂得多。UserManager的唯一构造函数有九个必需参数,我相信SignInManager需要七个 我能够走得足够远,以便执行测试,但模拟方法没有执行
OnGet()
方法。页面模型需要一个UserManager
和一个SignInManager
。我需要模拟需要这些类的SignInManager.IsSignedIn(ClaimsPrincipal用户)
方法。问题是ASP.NET核心中这些类的构造函数比以前ASP.NET版本的大多数解决方案文档要复杂得多。UserManager
的唯一构造函数有九个必需参数,我相信SignInManager
需要七个
我能够走得足够远,以便执行测试,但模拟方法没有执行
我的测试:
[Fact]
public void OnGet_UserIsSignedIn_RedirectsToIndex()
{
using (var testContext = new ApplicationDbContext(TestHelper.TestApplicationDbContextOptions()))
{
// Arrange
var mockUserStore = new Mock<IUserStore<AppUser>>();
var userManager = new UserManager<AppUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
var mockSignInManager = new Mock<SignInManager<AppUser>>(
userManager,
new HttpContextAccessor(),
new Mock<IUserClaimsPrincipalFactory<AppUser>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<ILogger<SignInManager<AppUser>>>().Object,
new Mock<IAuthenticationSchemeProvider>().Object,
new Mock<IUserConfirmation<AppUser>>().Object
);
var claimsPrincipal = new TestPrincipal(new Claim("name", "John Doe"));
var _mockConfig = new Mock<IConfiguration>();
var _mockUserValidator = new UserValidator<AppUser>();
var _mockLogger = new Mock<ILogger<RegisterModel>>();
var _mockEmailSender = new Mock<IEmailSender>();
var registerModel = new RegisterModel(_mockConfig.Object, userManager, mockSignInManager.Object, _mockUserValidator, _mockLogger.Object, _mockEmailSender.Object);
mockSignInManager.Setup(m => m.IsSignedIn(claimsPrincipal)).Returns(true);
var expected = new RedirectToPageResult("/Index");
// Act
var result = registerModel.OnGet();
//Assert
Assert.Equal(expected, result);
}
}
错误:
Error Message:
System.NullReferenceException : Object reference not set to an instance of an object.
Stack Trace:
at Project.Areas.Identity.Pages.Account.RegisterModel.CreateGateway() in ... line 150
RegisterModel构造函数:
public RegisterModel(
IConfiguration config,
UserManager<AppUser> userManager,
SignInManager<AppUser> signInManager,
UserValidator<AppUser> userValidator,
ILogger<RegisterModel> logger,
IEmailSender emailSender)
{
_config = config;
_userManager = userManager;
_signInManager = signInManager;
_userValidator = userValidator;
_logger = logger;
_emailSender = emailSender;
}
公共注册表模型(
i配置配置,
用户管理器用户管理器,
SignInManager SignInManager,
用户验证程序用户验证程序,
ILogger记录器,
电子邮件发送者(电子邮件发送者)
{
_config=config;
_userManager=userManager;
_signInManager=signInManager;
_userValidator=userValidator;
_记录器=记录器;
_emailSender=emailSender;
}
我的测试不仅感觉过于复杂,而且由于缺少对CreateGateway()
方法的依赖性,它未能触发IsSignedIn()mock方法,并在稍后的一行失败
简单地说:对于需要ASP.NET Core 3.0或更高版本的
UserManager
和SignInManager
的页面模型处理程序,我如何安排测试?本例中的问题是测试代码中的用户
if (_signInManager.IsSignedIn(User))
与设置中配置的主体不匹配
var claimsPrincipal = new TestPrincipal(new Claim("name", "John Doe"));
//...
mockSignInManager.Setup(m => m.IsSignedIn(claimsPrincipal)).Returns(true);
这会导致模拟在执行测试和评估条件时表现不符合预期
我建议使用It.IsAny()
mockSignInManager
.Setup(=>u.IsSignedIn(It.IsAny()))
.返回(真);
理想情况下,我会在PageModel中添加一个额外的抽象层,以简化它对所有这些实现问题的依赖
您还应该参考可用的文档,以获取有关如何对razor页面进行单元测试的提示
参考资料谢谢,您建议使用It.IsAny()
对该模拟工作很有帮助。我曾经使用过这个页面,但它使用的大多数都是琐碎的示例,除了数据访问层测试之外,我觉得这些示例没有什么帮助。您能更具体地说明页面模型的“附加抽象层”吗?
var claimsPrincipal = new TestPrincipal(new Claim("name", "John Doe"));
//...
mockSignInManager.Setup(m => m.IsSignedIn(claimsPrincipal)).Returns(true);
mockSignInManager
.Setup(_ => _.IsSignedIn(It.IsAny<ClaimsPrincipal>()))
.Returns(true);