NUnit测试用户管理器,asp.net核心中的角色管理器

时间:2019-03-04 18:42:05

标签: asp.net .net unit-testing asp.net-core nunit

我正在尝试为使用用户管理器和角色管理器的控制器编写单元测试。

我有一些操作,涉及创建用户,创建角色,在角色之间添加和删除用户。

我正在通过控制器构造函数将用户管理器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中的userManager和 测试项目是不同的实例。

我尝试使用Moq来模拟服务。但是,如果我要订购这些服务,就无法将它们传递给控制器​​实例。

如果我嘲笑控制器本身;我无法使用它的动作;返回Null;

我不完全理解模拟的概念。

解决上述问题的最佳方法是什么。 我正在使用Asp.Net Core 2.1和Nunit 3.0

谢谢:)

1 个答案:

答案 0 :(得分:1)

Its looks like you have not yet decoupled the dependencies out from the AdminController constructor.

Instead of passing the implementation you will need to pass the abstraction/interfaces:

public AdminController(IHostingEnvironment environment, 
                       ISignInManager<IdentityUser> signInManager, 
                       ILogger<LoginModel> logger, 
                       IRoleManager<IdentityRole> roleManager, 
                       IUserManager<IdentityUser> userManager)

Note that I've only added the I prefix, but it mean will need to refactor your code to pass an interfaces as I mentioned.

Now, we can mock the AdminController easily with:

[TestFixure]
public class AdminControllerTests
{
    private AdminController _adminController;
    private IHostingEnvironment _hostingEnvironment = new Mock<IHostingEnvironment>();
    private ISignInManager<IdentityUser> _signInManager = new Mock<ISignInManager<IdentityUser>>(); 

The _signInManager will need a setup that uses the method that returns ISignInManager within your ISignInManager, lets assume its name its Builder(). *Note there is other ways of mocking, here are 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, ...);
    }

Now you can make use of the _adminController instance (See proper naming convention for test methods):

    [Test]
    public void Verify_AdminController_Is_Decorated_With_Authorize_Attribute()
    {
        //...
        var actionResult = _adminController.AddUserToRole(user, userRole).Result;
        //...
    }
}