gpt4 book ai didi

c# - 单元测试依赖于 UserManager 和 RoleManager

转载 作者:行者123 更新时间:2023-11-30 16:04:06 27 4
gpt4 key购买 nike

我正在尝试对一些依赖于 UserManagerRoleManager 的方法进行单元测试,但遇到了一些困难。

我应该模拟 UserManagerRoleManager 然后将其传递给 AdminController 吗?或者我应该首先访问 AccountController 的默认 SignIn 操作并进行身份验证。我不确定如何执行这两个选项或解决此问题的最佳方法是什么。

当不验证/实例化管理器时,我在 UserManager

上得到 NullReferenceExceptions

我的测试

    [Test]
public void MaxRole_SuperAdmin()
{
var adminController = new AdminController();
var maxRole = adminController.GetMaxRole(SuperAdminUserId);

Assert.AreEqual(maxRole, "Super Admin");
}

Controller 和方法

[Authorize(Roles = "APGame Admin, APGame Investigator")]
[RequireHttps]
public class AdminController : Controller
{

private ApplicationUserManager _userManager;

public ApplicationUserManager UserManager
{
get { return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
private set { _userManager = value; }
}

private ApplicationRoleManager roleManager;

public ApplicationRoleManager RoleManager
{
get
{
return roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
}
private set { roleManager = value; }
}

public string GetMaxRole(string userId)
{
IEnumerable<string> userRoles = UserManager.GetRoles(userId);

string role = null;

if (userRoles.Contains("APGame Admin"))
{
if (userRoles.Contains("TeVelde Group") && userRoles.Contains("Genomics Group"))
role = "Super Admin";

else role = "Admin";
}

else if (userRoles.Contains("APGame Investigator"))
{
role = "Investigator";
}

else if (userRoles.Contains("APGame User"))
{
role = "User";
}

else
{
//TODO: Log no role, HIGH
}

return role;
}
}

最佳答案

如果你关注了我的博文,你应该知道 ApplicationUserManager 的构造函数是这样的:

public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store)
{
// configuration-blah-blah
}
}

并且您的 Controller 应该将用户管理器对象注入(inject)到构造函数中:

public class AdminController : Controller
{
private readonly ApplicationUserManager userManager;
public AdminController(ApplicationUserManager userManager)
{
this.userManager = userManager;
}
}

现在进行测试 - 您需要一个模拟框架。几年前,我曾经在每个测试中都放入 MOQ,现在首选的模拟框架是 NSubstitue,因为它的语法更具可读性。目前我很少使用模拟替代品并且更喜欢集成测试,甚至是深入研究数据库,但这不是这个问题/讨论的目标。

因此,为了进行测试,您需要创建被测系统 (SUT) - AdminController:

[Test]
public void MaxRole_SuperAdmin()
{
var userStoreStub = NSubstitute.Substitute.For<IUserStore<ApplicationUser>>();
var userManager = new ApplicationUserManager(userStoreStub);
var sut = new AdminController(userManager);

//TODO set up method substitutions on userStoreStub - see NSubstitute documentation

var maxRole = sut.GetMaxRole(SuperAdminUserId);

Assert.AreEqual(maxRole, "Super Admin");
}

但这是非常笨拙的测试。您正在尝试测试太深的东西。我建议您将 GetMaxRole 记录从 Controller 移到一个单独的类中 - 一个服务类,或者这可以是 ApplicationUserManager 的一部分,也可以是 QueryHandler 如果你愿意的话。无论你怎么调用它,它都不应该真正成为 Controller 的一部分。我认为这个方法实际上属于ApplicationUserManager。这样你的测试层就减少了一个,你只需要创建用户管理器类,而不是 Controller 。

鉴于 GetMaxRole() 方法是 ApplicationUserManager 的一部分,您的测试将变得更小:

[Test]
public void MaxRole_SuperAdmin()
{
var userStoreStub = NSubstitute.Substitute.For<IUserStore<ApplicationUser>>();
var sut = new ApplicationUserManager(userStoreStub);

//TODO set up method substitutions on userStoreStub - see NSubstitute documentation

var maxRole = sut.GetMaxRole(SuperAdminUserId);

Assert.AreEqual(maxRole, "Super Admin");
}

将测试方法从 Controller 中移出的原因如下:

  • 随着时间的推移,我发现 Controller 很容易随着新的依赖项的添加/删除/替换而经常更改。而且,如果您围绕 Controller 进行了一些测试,则必须更改每个测试更改的依赖项。
  • 如果您要在AdminController 之外的其他地方使用GetMaxRole 方法,您就有麻烦了。除了提供 HTTP(S) 端点之外, Controller 并不意味着共享方法。
  • 您方法的逻辑看起来像域逻辑或业务逻辑。这应该彻底测试。 Controller 不容易测试,因为它们处理 HTTP 请求和 HttpContext,这不容易测试(尽管可能)。此外,最好避免将 Controller 的东西与业务逻辑混合 - 帮助您避免意大利面条代码综合症。

我可以一直讨论这个话题,但最好阅读 DI book by Mark SeemanUnit Testing book by Roy Osherove .

关于c# - 单元测试依赖于 UserManager 和 RoleManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35733185/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com