模拟ApplicationUserManager用于单元测试MVC控制器
本文关键字:MVC 控制器 单元测试 用于 ApplicationUserManager 模拟 | 更新日期: 2023-09-27 17:53:39
我想知道是否有人能帮我解决这个问题。
我正在为一个特定的控制器编写单元测试。这个控制器继承自一个BaseController并且BaseController有这个属性:
private ApplicationUserManager userManager;
public ApplicationUserManager UserManager
{
get { return this.userManager ?? this.Request.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
set { this.userManager = value; }
}
ApplicationUserManager的变量是:
public ApplicationUserManager(IUserStore<ApplicationUser> store, IIdentityMessageService emailService)
: base(store)
{
this.EmailService = emailService;
var dataProtectionProvider = Startup.DataProtectionProvider;
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
这是我模拟ApplicatonUserManager类所做的:
var store = new Mock<IUserStore<ApplicationUser>>();
var emailService = new Mock<IIdentityMessageService>();
var applicationUserManager = new Mock<ApplicationUserManager>(store.Object, emailService.Object);
this.targetController.UserManager = applicationUserManager.Object;
var dataprotectionprovided = new Mock<IDataProtectionProvider>();
applicationUserManager.Setup(r => r.UserTokenProvider).Returns(new DataProtectorTokenProvider<ApplicationUser, string>(dataprotectionprovided.Object.Create("ASP.NET Identity")));
this.targetController.UserManager = applicationUserManager.Object;
我试图模拟这个,但因为这不是虚拟属性(UserTokenProvider),它不允许我,我得到这个异常:
System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: r => r.UserTokenProvider
有谁能帮我解决这个问题吗?我只是想模拟这个,以便测试从具有该属性的BaseController继承的控制器。
谢谢
谢谢你的帮助@bwyn
根据你的建议,我已经设法把它解决了。刚刚为ApplicationUserManager创建了一个新的构造函数,如下所示:public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store)
{
}
然后是单元测试:
var user = new ApplicationUser { User = new User { UserId = 1 } };
var store = new Mock<IUserStore<ApplicationUser>>(MockBehavior.Strict);
store.As<IUserStore<ApplicationUser>>().Setup(x => x.FindByIdAsync(It.IsAny<string>())).ReturnsAsync(user);
this.targetController.UserManager = new ApplicationUserManager(store.Object);
谢谢大家!
正如您在回答中的一个评论中指出的那样,创建额外的构造函数可能导致其他开发人员使用错误的构造函数。
我建议你试试下面的方法。
将原始ApplicationUserManager构造函数中的代码移动到一个新的受保护的虚拟方法中。然后修改现在为空的构造函数以调用new virtual方法。
public class ApplicationUserManager
{
public ApplicationUserManager(IUserStore<ApplicationUser> store, IIdentityMessageService emailService)
: base(store)
{
CalledAfterConstruction();
}
protected virtual void CalledAfterConstruction()
{
this.EmailService = emailService;
var dataProtectionProvider = Startup.DataProtectionProvider;
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
}
现在创建一个新的MockApplicationUserManager类,当单元测试继承了ApplicationUserManager,重写继承的' callledafterconstruction '与一个空的方法,你几乎有东西的方式你在你的答案。
public class MockClass : ApplicationUserManager
{
public MockClass(IUserStore<ApplicationUser> store, IIdentityMessageService emailService) : base(store, emailService)
{
}
protected override void CalledAfterContruction()
{
}
}
是的,这有点复杂,但它确实可以防止人们滥用你的原始类