2013-03-11 28 views
4

希望这不是一个愚蠢的问题。我一直在寻找两天的方法来模拟我的操作对system.web.security.roles的调用。模拟控制器动作单元测试的默认角色提供者

我希望我的单元测试是独立的,不涉及调用外部资源,比如角色获取的数据库。

我发现的所有答案都建议创建一个自定义角色提供者,但我更喜欢嘲笑制作假货。

我得到的最接近的是这个solution但我没有找到一种方法让ninject在测试之外运行项目时将默认角色提供程序传递给构造函数。

我知道类型Mock提供了一个更简单的解决方案,但是我正在使用rhino Mocks,现在已经太迟了。

回答

10

我已经有像你一样的问题,经过两个小时的搜索,我放弃了。

最后我最终创建了自己的模拟角色提供程序 - 代码如下。

public class MockRoleProvider : RoleProvider 
{ 
    public MockRoleProvider() 
     : base() 
    { 
     Users = new List<User>(); 
     Roles = new List<Role>(); 
    } 

    #region RoleProvider members 
    public override void AddUsersToRoles(string[] usernames, string[] roleNames) 
    { 
     if (usernames == null) throw new ArgumentNullException("usernames"); 
     if (roleNames == null) throw new ArgumentNullException("roleNames"); 

     foreach (string role in roleNames) 
     { 
      if (!RoleExists(role)) throw new ProviderException("Role name does not exist."); 
     } 

     foreach (string user in usernames) 
     { 
      if (Users.FirstOrDefault(u => u.Username == user) == null) throw new ProviderException("Username does not exist."); 
     } 

     foreach (string username in usernames) 
     { 
      User user = Users.FirstOrDefault(u => u.Username == username); 
      if (user == null) continue; 
      foreach (var rolename in roleNames) 
      { 
       Role role = Roles.FirstOrDefault(r => r.RoleName == rolename); 
       user.Roles.Add(role); 
       role.Users.Add(user); 
      } 
     } 
    } 

    public override string ApplicationName { get; set; } 

    public override void CreateRole(string roleName) 
    { 
     if (roleName == null || roleName == "") throw new ProviderException("Role name cannot be empty or null."); 
     if (roleName.Contains(",")) throw new ArgumentException("Role names cannot contain commas."); 
     if (RoleExists(roleName)) throw new ProviderException("Role name already exists."); 

     Roles.Add(new Role { RoleName = roleName }); 
    } 

    public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) 
    { 
     if (roleName == null || roleName == "") throw new ProviderException("Role name cannot be empty or null."); 

     Role role = Roles.FirstOrDefault(r => r.RoleName == roleName); 

     if (role == null) throw new ProviderException("Role name does not exist."); 
     if (throwOnPopulatedRole && GetUsersInRole(roleName).Length > 0) throw new ProviderException("Cannot delete a populated role."); 

     Roles.Remove(Roles.FirstOrDefault(r => r.RoleName == roleName)); 
     return true; 
    } 

    public override string[] FindUsersInRole(string roleName, string usernameToMatch) 
    { 
     return GetUsersInRole(roleName).Where(n => n.Contains(usernameToMatch)).ToArray(); 
    } 

    public override string[] GetAllRoles() 
    { 
     return Roles.Select(r => r.RoleName).ToArray(); 
    } 

    public override string[] GetRolesForUser(string username) 
    { 
     if (username == null || username == "") throw new ProviderException("User name cannot be empty or null."); 

     User user = Users.FirstOrDefault(u => u.Username == username); 

     if (user == null) return new string[0]; 

     return user.Roles.Select(r => r.RoleName).ToArray(); 
    } 

    public override string[] GetUsersInRole(string roleName) 
    { 
     if (roleName == null || roleName == "") throw new ProviderException("Role name cannot be empty or null."); 

     Role role = Roles.FirstOrDefault(r => r.RoleName == roleName); 

     if (role == null) throw new ProviderException("Role '" + roleName + "' does not exist."); 

     return role.Users.Select(u => u.Username).OrderBy(n => n).ToArray(); 
    } 

    public override bool IsUserInRole(string username, string roleName) 
    { 
     if (username == null || username == "") throw new ProviderException("User name cannot be empty or null."); 
     if (roleName == null || roleName == "") throw new ProviderException("Role name cannot be empty or null."); 

     Role role = Roles.FirstOrDefault(r => r.RoleName == roleName); 

     return role != null && role.Users.FirstOrDefault(u => u.Username == username) != null; 
    } 

    public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) 
    { 
     foreach (string roleName in roleNames) 
     { 
      if (roleName == null || roleName == "") throw new ProviderException("Role name cannot be empty or null."); 
      if (!RoleExists(roleName)) throw new ProviderException("Role name not found."); 
     } 

     foreach (string username in usernames) 
     { 
      if (username == null || username == "") throw new ProviderException("User name cannot be empty or null."); 

      foreach (string roleName in roleNames) 
      { 
       if (!IsUserInRole(username, roleName)) throw new ProviderException("User is not in role."); 
      } 
     } 

     foreach (string username in usernames) 
     { 
      User user = Users.FirstOrDefault(u => u.Username == username); 
      if (user == null) continue; 
      foreach (string roleName in roleNames) 
      { 
       Role role = user.Roles.FirstOrDefault(r => r.RoleName == roleName); 
       role.Users.Remove(user); 
       user.Roles.Remove(role); 
      } 
     } 
    } 

    public override bool RoleExists(string roleName) 
    { 
     if (roleName == null || roleName == "") throw new ProviderException("Role name cannot be empty or null."); 

     return Roles.FirstOrDefault(r => r.RoleName == roleName) != null; 
    } 
    #endregion 

    public void ClearAll() 
    { 
     Users = new List<User>(); 
     Roles = new List<Role>(); 
    } 

    public void ClearRoles() 
    { 
     Roles = new List<Role>(); 
     Users.ForEach(u => u.Roles = new List<Role>()); 
    } 

    public void ClearUsers() 
    { 
     Users = new List<User>(); 
     Roles.ForEach(r => r.Users = new List<User>()); 
    } 

    public void CreateUser(string username) 
    { 
     if (username == null || username == "") throw new ProviderException("User name cannot be empty or null."); 
     if (UserExists(username)) throw new ProviderException("User name already exists."); 

     Users.Add(new User { Username = username }); 
    } 

    public bool DeleteUser(string username) 
    { 
     if (username == null || username == "") throw new ProviderException("User name cannot be empty or null."); 

     User user = Users.FirstOrDefault(u => u.Username == username); 

     if (user == null) throw new ProviderException("User name does not exist."); 

     foreach (Role role in user.Roles) 
     { 
      role.Users.Remove(user); 
     } 
     Users.Remove(user); 
     return true; 
    } 

    public bool UserExists(string username) 
    { 
     if (username == null || username == "") throw new ProviderException("User name cannot be empty or null."); 

     return Users.FirstOrDefault(u => u.Username == username) != null; 
    } 

    private List<Role> Roles { get; set; } 

    private List<User> Users { get; set; } 

    private class Role 
    { 
     public Role() 
     { 
      Users = new List<User>(); 
     } 

     public string RoleName { get; set; } 
     public List<User> Users { get; set; } 
    } 

    private class User 
    { 
     public User() 
     { 
      Roles = new List<Role>(); 
     } 

     public string Username { get; set; } 
     public List<Role> Roles { get; set; } 
    } 
} 

这是真正的基础,但完全实现RoleProvider。

对于使用MockRoleProvider添加到您的app.config XML的这一行到<configuration>元素:

<system.web> 
    <roleManager enabled="true" defaultProvider="MockRoleProvider"> 
    <providers> 
     <add name="MockRoleProvider" type="YourProject.Tests.MockRoleProvider, YourProject.Tests"/> 
    </providers> 
    </roleManager> 
</system.web> 

然后在单元测试中安排部分使用此代码:

MockRoleProvider mock = Roles.Provider as MockRoleProvider; 
if (mock == null) throw new NullReferenceException("MockRoleProvider null exception."); 
mock.ClearAll(); 
mock.CreateUser("SomeUser"); 
mock.CreateRole("SomeRole"); 
mock.AddUsersToRoles(new string[] { "SomeUser" }, new string[] { "SomeRole" }); 
+0

我只是设置这和它工作很好,所以我upvoted。 – 2014-09-02 17:07:23

+0

这工作就像一个魅力,谢谢。 – 2017-03-21 12:20:49

+0

N4n0应该真的接受这个,这是一个很好的解决方案,upvoted。 – 2017-05-02 09:07:27