单元测试(mvc) - 带角色的问题

时间:2011-01-04 15:11:19

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

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

3 个答案:

答案 0 :(得分:11)

我在编码单元测试中尝试模拟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);

希望这有帮助。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

您可以使用Predicate / Func创建一个光包装。

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

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

MyClass.IsUserInRole = role => true;

如果您不想使用公共静态,可以通过构造函数注入Predicate并将其作为私有readonly存储。

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

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

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());