2013-03-11 30 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