C# 在测试派生类时,如何模拟i基方法
我有一个问题,我想在我的用户服务中编写一个自定义函数的单元测试。但此用户服务源自asp.net核心标识用户管理器。我想扩展用户管理器的功能,因此我从中派生。 所以我想测试CreateCRohMUserAsync方法C# 在测试派生类时,如何模拟i基方法,c#,unit-testing,.net-core,asp.net-identity,C#,Unit Testing,.net Core,Asp.net Identity,我有一个问题,我想在我的用户服务中编写一个自定义函数的单元测试。但此用户服务源自asp.net核心标识用户管理器。我想扩展用户管理器的功能,因此我从中派生。 所以我想测试CreateCRohMUserAsync方法 公共类UserService:UserManager,IUserService { 公共用户服务(IUserStore存储, IOPS选项访问器, IPasswordHasher密码hasher, IEnumerable用户验证程序, IEnumerable密码验证器, ILooku
公共类UserService:UserManager,IUserService
{
公共用户服务(IUserStore存储,
IOPS选项访问器,
IPasswordHasher密码hasher,
IEnumerable用户验证程序,
IEnumerable密码验证器,
ILookupNormalizer-keyNormalizer、IdentityerRorDescriptiber错误、IServiceProvider服务、ILogger记录器):基本(存储、选项访问器、密码哈希器、用户验证器、密码验证器、keyNormalizer、错误、服务、记录器)
{
}
公共异步任务CreateCRohMUserAsync(用户)
{
PasswordGenerator pwGenerator=新的PasswordGenerator();
var password=pwGenerator.Generate();
user.UserName=GetUniqueUserName(user.FirstName,user.LastName);
var result=await base.CreateAsync(用户,密码);
if(result.successed)
{
//TODO:向创建的用户发送邮件
}
返回结果;
}
公共字符串GetUniqueUserName(字符串firstName,字符串lastName)
{
if(string.IsNullOrEmpty(firstName))
{
抛出新ArgumentNullException(nameof(firstName),“firstName不能为null”);
}
if(string.IsNullOrEmpty(lastName))
{
抛出新ArgumentNullException(nameof(lastName),“lastName不能为null”);
}
返回lastName+firstName.Substring(0,2)+Users.Count()+1;
}
}
}
在单元测试中,我想模拟基类的base.CreateAsync(user,password)和Users.Count()功能。但我不知道怎么做。
还是我的实现错了?如何对这种方法进行单元测试?根据您的示例代码,我建议您将继承更改为组合,因为您只使用基类中的方法,而不重写任何方法
interface IUserManager
{
IdentityResult CreateAsync();
}
class DefaultUserManager : IUserManager
{
public DefaultUserManager(UserManager<User> manager)
{
}
public IdentityResult CreateAsync()
{
// Call UserManager<User>
}
}
public class UserService : IUserService
{
private readonly IUserManager _userManager;
public UserService(IUserManager userManager, ...)
{
_userManager = userManager;
}
public async Task<IdentityResult> CreateCRohMUserAsync(User user)
{
var result = await _userManager.CreateAsync();
return result;
}
}
界面管理器
{
IdentityResult CreateAsync();
}
类DefaultUserManager:IUserManager
{
公共默认用户管理器(用户管理器)
{
}
公共标识Result CreateAsync()
{
//呼叫用户管理器
}
}
公共类UserService:IUserService
{
专用只读IUserManager\u userManager;
公共用户服务(IUserManager用户管理器,…)
{
_userManager=userManager;
}
公共异步任务CreateCRohMUserAsync(用户)
{
var result=await_userManager.CreateAsync();
返回结果;
}
}
我将
UserManager
的使用抽象为一个名为IUserManager
的接口,而实现仍然使用UserManager
。然而,您的UserService
调用接口,因此在单元测试中,您可以简单地提供IUserManager
的模拟实例,并避免调用UserManager
,根据您的示例代码,我建议您将继承更改为composition,因为您只使用基类中的方法,不覆盖任何
interface IUserManager
{
IdentityResult CreateAsync();
}
class DefaultUserManager : IUserManager
{
public DefaultUserManager(UserManager<User> manager)
{
}
public IdentityResult CreateAsync()
{
// Call UserManager<User>
}
}
public class UserService : IUserService
{
private readonly IUserManager _userManager;
public UserService(IUserManager userManager, ...)
{
_userManager = userManager;
}
public async Task<IdentityResult> CreateCRohMUserAsync(User user)
{
var result = await _userManager.CreateAsync();
return result;
}
}
界面管理器
{
IdentityResult CreateAsync();
}
类DefaultUserManager:IUserManager
{
公共默认用户管理器(用户管理器)
{
}
公共标识Result CreateAsync()
{
//呼叫用户管理器
}
}
公共类UserService:IUserService
{
专用只读IUserManager\u userManager;
公共用户服务(IUserManager用户管理器,…)
{
_userManager=userManager;
}
公共异步任务CreateCRohMUserAsync(用户)
{
var result=await_userManager.CreateAsync();
返回结果;
}
}
我将UserManager
的使用抽象为一个名为IUserManager
的接口,而实现仍然使用UserManager
。然而,您的UserService
调用接口,因此在单元测试中,您可以简单地提供一个IUserManager
的模拟实例,并避免调用您正在使用的UserManager
首先,您必须删除CreateCRohMUserAsync
中的base
关键字:
var result = await CreateAsync(user, password); // Previously base.CreateAsync
如果存在,基类的实现总是被调用-mockCreateAsync
将无效(moq通过重写方法来模拟方法)
删除base
后,可以像这样测试CreateCRohMUserAsync
:
[事实]
public async void CreateCRohMUserAsync_DoesMething()
{
//安排
...
Mock mockTestSubject=new Mock(…);//将通常传递给UserService构造函数的服务传递给
mockTestSubject.CallBase=true;//因此,当您调用CreateCRohMUserAsync时,您定义的逻辑将运行
mockTestSubject.Setup(t=>t.CreateAsync(…).ReturnsAsync(…);//Mock CreateAsync
//如果GetUniqueUserName是虚拟的,您也可以模拟它
//mockTestSubject.Setup(t=>t.GetUniqueUserName(…)。返回(…);
//表演
IdentityResult结果=等待mockTestSubject.Object.CreateCRohMUserAsync(…);
//断言
...
}
同样的模式也适用于GetUniqueUserName
基本上:
- 模拟派生类,以便可以设置基类的虚拟成员李>
- 将
设置为true,以便可以运行在派生类中定义的逻辑CallBase
- 您正在使用的ASUMING
首先,您必须删除
CreateCRohMUserAsync
中的base
关键字:
var result = await CreateAsync(user, password); // Previously base.CreateAsync
如果存在,基类的实现总是被调用-mockCreateAsync
将无效(moq通过重写方法来模拟方法)
移除base
后,可以测试C