2013-03-11 3 views
4

희망없는 질문입니다. 나는 이틀 동안 내 행동에 대해 system.web.security.roles에 대한 호출을 모의 할 방법을 찾고 있었다.컨트롤러의 액션 유닛 테스트를위한 모의 기본 역할 제공자

단위 테스트를 격리하고 역할이 저장되는 데이터베이스와 같은 외부 리소스에 대한 호출을 필요로하지 않습니다.

내가 찾은 모든 대답은 사용자 지정 역할 공급자의 생성을 제안했지만 가짜 만들기보다는 조롱하는 것이 좋습니다.

가장 가까운 것은이 solution과 같았습니다.하지만 테스트 외부에서 프로젝트를 실행할 때 ninject가 기본 역할 공급자를 생성자에 전달하는 방법을 찾지 못했습니다.

나는 모의 (Mock)이 이것에 대한보다 쉬운 해결책을 제공한다는 것을 알고 있지만, 나는 코뿔소 모의 (mock)를 사용하고 있으며, 지금 변경하기에는 너무 늦다.

답변

10

나는 너와 같은 문제를 겪었고, 2 시간 동안 찾은 후에 나는 그것을 포기했다.

마침내 나는 자신의 조롱 역할 공급자 - 코드 울부 짖음을 만들었습니다.

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의 전체 구현입니다.

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

그런 다음 단위 테스트에 배치 부품 사용이 코드 : 사용하기 위해

가 MockRoleProvider 당신이 <configuration> 요소로 XML의 라인의 app.config에 추가 난 그냥이 설정

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. –

+0

이것은 매력처럼 작동했습니다. 감사합니다. –

+0

N4n0이 이것을 실제로 받아 들여야합니다. 좋은 해결책입니다. –