【问题标题】:Unit Test(mvc) -problem with Roles单元测试(mvc) - 角色问题
【发布时间】:2011-06-03 11:09:27
【问题描述】:

我有 mvc 应用程序,我正在使用 poco 对象并编写单元测试。问题是当他们到达这行代码 Roles.IsUserInRole("someUser", "role") 时,我的所有测试都失败了。我应该为角色实现新的接口或存储库还是......? 谢谢

【问题讨论】:

  • 这里没有足够的信息来回答您的问题。请考虑修改/添加代码/为您的问题添加详细信息。
  • 他们为什么会失败?您可以发布异常的详细信息以及您使用的框架吗?大多数框架都使用异常类型来表示失败,因此可能是由于测试的隔离而导致的失败或异常。
  • 我已经在控制器中实现了角色测试,类似于unit-testing-security-model-clickonce
  • 这是错误消息:System.Configuration.Provider.ProviderException:角色管理器功能尚未启用。

标签: asp.net-mvc unit-testing security-roles user-roles


【解决方案1】:

您可以使用 Predicate/Func 创建一个轻量级包装器。

public static Predicate<string> IsUserInRole = role => Roles.IsUserInRole(role);

然后使用 IsUserInRole() 代替 Roles.IsUserInRole()。在运行时,您会得到相同的行为。但是在测试时,您可以覆盖该函数,使其不访问 RoleProvider

MyClass.IsUserInRole = role => true;

如果您不想拥有公共静态,您可以通过构造函数注入谓词并将其存储为私有只读。

class MyClass
{    
    private readonly Predicate<string> IsUserInRole;
    MyClass(Predicate<string> roleChecker) { this.IsUserInRole = roleChecker }
    MyClass() : this(role => Roles.IsUserInRole(role)) { }
}

如果你使用 Moq,你可以返回一个 mock,然后控制返回值和/或检查方法是否被调用。并检查发送到谓词的参数值。

Mock<Predicate<string>> mockRoleChecker = new Mock<Predicate<string>>();
var cut = new MyClass(mockRoleChecker.Object);
var expectedRole = "Admin";
mockRoleChecker.SetReturnsDefault<bool>(true);  // if not specified will return false which is default(bool)

cut.MyMethod();

mockRoleChecker.Verify(x => x(expectedRole), Times.Once());

【讨论】:

    【解决方案2】:

    您可以设置一个自定义方法来检查在测试中表现不同的角色,但我更喜欢让测试设置一个可以与标准方法一起使用的上下文。

    http://stephenwalther.com/blog/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-context.aspx

    【讨论】:

      【解决方案3】:

      在我的编码单元测试中尝试模拟 Roles.IsUserInRole 功能时,我遇到了同样的问题。我的解决方案是创建一个名为 RoleProvider 的新类和一个带有方法 IsUserInRole 的接口,然后调用 System.Web.Security.Roles.IsUserInRole:

      public class RoleProvider: IRoleProvider
      {
          public bool IsUserInRole(IPrincipal userPrincipal)
          {
              return System.Web.Security.Roles.IsUserInRole(userPrincipal.Identity.Name, "User");
          }
      }
      

      然后在我的代码中调用 RoleProvider IsUserInRole 方法。由于您有一个接口,因此您可以在测试中模拟 IRoleProvider,此处显示的示例是使用 Rhino Mocks:

      var roleProvider = MockRepository.GenerateStub<IRoleProvider>();
      roleProvider.Expect(rp => rp.IsUserInRole(userPrincipal)).Return(true);
      

      希望这会有所帮助。

      【讨论】:

      • 这对于可测试性来说非常出色。不过,我的控制器现在需要一个 RoleProvider 实例,这有点烦人。最终可能会创建一个内置的基本控制器类(以及一些其他常见的属性/字段)。感谢您的建议!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-23
      相关资源
      最近更新 更多