ASP.NET Core 中的 NUnit 测试 UserManager、roleManager
NUnit Test UserManager, roleManager in ASP.NET Core
我正在尝试为使用 User Manager 和 Role Manager.
的控制器编写单元测试
我有操作,涉及到创建用户、创建角色,以及在角色中添加和删除用户。
我正在通过控制器构造函数将 usermanager、signInManager 作为依赖项传递。
private readonly IHostingEnvironment hostingEnvironment;
public IHostingEnvironment HostingEnvironment => hostingEnvironment;
public AdminController(IHostingEnvironment environment, SignInManager<IdentityUser> signInManager, ILogger<LoginModel> logger, RoleManager<IdentityRole> roleManager, UserManager<IdentityUser> userManager)
{
_signInManager = signInManager;
_logger = logger;
_roleManager = roleManager;
_userManager = userManager;
hostingEnvironment = environment;
}
我需要测试用户是否成功添加到角色、从角色中删除等
我不想测试服务本身,只想测试操作。
我已将操作解耦如下以捕获任何异常。
public async Task<bool> AddUserToRole(IdentityUser user, string role)
{
try
{
var addUserToRole = await _userManager.AddToRoleAsync(user, role);
if (addUserToRole.Succeeded)
{
return true;
}
else
{
return false;
}
}
catch(Exception e)
{
throw new Exception("OperationFailed");
}
return false;
}
同样,我解耦了所有涉及 userManager 的操作,并在控制器操作中调用了上述函数。
为了测试,我做了以下工作:
[TestFixture]
public class AdminControllerTest
{
protected TestContext db;
protected Context _db;
protected SignInManager<IdentityUser> signInManager;
protected ILogger<LoginModel> logger;
protected RoleManager<IdentityRole> roleManager;
protected UserManager<IdentityUser> userManager;
protected IHostingEnvironment hostingEnvironment;
[TestCase]
public void Verify_AdminController_Is_Decorated_With_Authorize_Attribute()
{
var userEmail = _db.AspNetUsers.Select(x => x.Email).FirstOrDefault();
var user =await userManager.FindByEmailAsync(userEmail);
var userRole = "Supervisor";
AdminController adminController = new AdminController(hostingEnvironment, signInManager, logger, roleManager, userManager);
var actionResult = adminController.AddUserToRole(user, userRole).Result;
Assert.IsTrue(actionResult);
}
上面的方法不行。
- 我相信这是因为; DevProject 和 Test Project 中的 userManager 是不同的实例。
我尝试使用 Moq 模拟服务。但是如果我模拟服务,我不能将它们传递给控制器实例。
如果我模拟控制器本身,我将无法使用它的动作;它 returns 空;
我不完全理解模拟的概念。
解决上述问题的最佳方法是什么?
我正在使用 ASP.NET Core 2.1 和 NUnit 3.0。
看起来您还没有将依赖项与 AdminController
构造函数分离。
您需要传递 abstraction/interfaces:
而不是传递实现
public AdminController(IHostingEnvironment environment,
ISignInManager<IdentityUser> signInManager,
ILogger<LoginModel> logger,
IRoleManager<IdentityRole> roleManager,
IUserManager<IdentityUser> userManager)
请注意,我只添加了 I
前缀,但这意味着需要重构您的代码以传递我提到的接口。
现在,我们可以通过以下方式轻松模拟 AdminController
:
[TestFixure]
public class AdminControllerTests
{
private AdminController _adminController;
private IHostingEnvironment _hostingEnvironment = new Mock<IHostingEnvironment>();
private ISignInManager<IdentityUser> _signInManager = new Mock<ISignInManager<IdentityUser>>();
_signInManager
需要一个使用 ISignInManager
中的 returns ISignInManager 方法的设置,假设它的名字是 Builder()
.
注意:还有其他的模拟方式。这里是 two ways, or consider using autofac.
[SetUp]
public void SetUp()
{
_signInManager.Setup(a => a.Builder()).Returns(new[] { new IdentityUser() });
// Do the same for the rest of the dependencies.
//...
_adminController = new AdminController(_hostingEnvironment, _signInManager.Object, ...);
}
现在您可以使用 _adminController
实例(测试方法见 proper naming convention):
[Test]
public void Verify_AdminController_Is_Decorated_With_Authorize_Attribute()
{
//...
var actionResult = _adminController.AddUserToRole(user, userRole).Result;
// ...
}
}
我正在尝试为使用 User Manager 和 Role Manager.
的控制器编写单元测试我有操作,涉及到创建用户、创建角色,以及在角色中添加和删除用户。
我正在通过控制器构造函数将 usermanager、signInManager 作为依赖项传递。
private readonly IHostingEnvironment hostingEnvironment;
public IHostingEnvironment HostingEnvironment => hostingEnvironment;
public AdminController(IHostingEnvironment environment, SignInManager<IdentityUser> signInManager, ILogger<LoginModel> logger, RoleManager<IdentityRole> roleManager, UserManager<IdentityUser> userManager)
{
_signInManager = signInManager;
_logger = logger;
_roleManager = roleManager;
_userManager = userManager;
hostingEnvironment = environment;
}
我需要测试用户是否成功添加到角色、从角色中删除等
我不想测试服务本身,只想测试操作。
我已将操作解耦如下以捕获任何异常。
public async Task<bool> AddUserToRole(IdentityUser user, string role)
{
try
{
var addUserToRole = await _userManager.AddToRoleAsync(user, role);
if (addUserToRole.Succeeded)
{
return true;
}
else
{
return false;
}
}
catch(Exception e)
{
throw new Exception("OperationFailed");
}
return false;
}
同样,我解耦了所有涉及 userManager 的操作,并在控制器操作中调用了上述函数。
为了测试,我做了以下工作:
[TestFixture]
public class AdminControllerTest
{
protected TestContext db;
protected Context _db;
protected SignInManager<IdentityUser> signInManager;
protected ILogger<LoginModel> logger;
protected RoleManager<IdentityRole> roleManager;
protected UserManager<IdentityUser> userManager;
protected IHostingEnvironment hostingEnvironment;
[TestCase]
public void Verify_AdminController_Is_Decorated_With_Authorize_Attribute()
{
var userEmail = _db.AspNetUsers.Select(x => x.Email).FirstOrDefault();
var user =await userManager.FindByEmailAsync(userEmail);
var userRole = "Supervisor";
AdminController adminController = new AdminController(hostingEnvironment, signInManager, logger, roleManager, userManager);
var actionResult = adminController.AddUserToRole(user, userRole).Result;
Assert.IsTrue(actionResult);
}
上面的方法不行。
- 我相信这是因为; DevProject 和 Test Project 中的 userManager 是不同的实例。
我尝试使用 Moq 模拟服务。但是如果我模拟服务,我不能将它们传递给控制器实例。
如果我模拟控制器本身,我将无法使用它的动作;它 returns 空;
我不完全理解模拟的概念。
解决上述问题的最佳方法是什么?
我正在使用 ASP.NET Core 2.1 和 NUnit 3.0。
看起来您还没有将依赖项与 AdminController
构造函数分离。
您需要传递 abstraction/interfaces:
而不是传递实现public AdminController(IHostingEnvironment environment,
ISignInManager<IdentityUser> signInManager,
ILogger<LoginModel> logger,
IRoleManager<IdentityRole> roleManager,
IUserManager<IdentityUser> userManager)
请注意,我只添加了 I
前缀,但这意味着需要重构您的代码以传递我提到的接口。
现在,我们可以通过以下方式轻松模拟 AdminController
:
[TestFixure]
public class AdminControllerTests
{
private AdminController _adminController;
private IHostingEnvironment _hostingEnvironment = new Mock<IHostingEnvironment>();
private ISignInManager<IdentityUser> _signInManager = new Mock<ISignInManager<IdentityUser>>();
_signInManager
需要一个使用 ISignInManager
中的 returns ISignInManager 方法的设置,假设它的名字是 Builder()
.
注意:还有其他的模拟方式。这里是 two ways, or consider using autofac.
[SetUp]
public void SetUp()
{
_signInManager.Setup(a => a.Builder()).Returns(new[] { new IdentityUser() });
// Do the same for the rest of the dependencies.
//...
_adminController = new AdminController(_hostingEnvironment, _signInManager.Object, ...);
}
现在您可以使用 _adminController
实例(测试方法见 proper naming convention):
[Test]
public void Verify_AdminController_Is_Decorated_With_Authorize_Attribute()
{
//...
var actionResult = _adminController.AddUserToRole(user, userRole).Result;
// ...
}
}