2015-03-18 3 views
3

Я прочитал много блогов и комментариев о Mocking объекта сеанса или использовании поддельных объектов, но я до сих пор не могу перевести эти ответы на свой собственный код.ASP.NET MVC5: Unit Тестирование контроллера сеансом

Вот индекс Действие моего UserController, которая использует инъекции зависимостей, чтобы ввести IUserRepository в конструктор:

// GET: User 
    public ActionResult Index() 
    { 
     User user = (User) Session["CurrentUser"]; 
     if (user != null) { 
      if(_repository.UserHasAdminAcces(user)) 
       return View(_repository.GetAllUsers().ToList()); 

      return RedirectToAction("DisplayErrorPage", "Error", new { errorMessage = "You have to be an Admin to enter this part" }); 
     } 
     return RedirectToAction("Login"); 
    } 

Мой метод испытаний в настоящее время выглядит следующим образом:

public void TestIndexForValidUser() 
    {   
     var mock = new Mock<IUserRepository>(); 
     mock.Setup(x => x.UserHasAdminAcces(It.IsAny<User>())).Returns(true); 

     UserController target = new UserController(mock.Object); 

     // create mock HttpContext 
     var context = new Mock<ControllerContext>(); 

     target.ControllerContext = context.Object; 

     var result = target.Index() as ViewResult; 

     Assert.AreEqual(result, "Index"); 

    } 

Я хочу дать ControllerContext объект сеанса, который возвращает поддельного пользователя, и убедитесь, что возвращен вид, называемый индексом.

+0

Возможный дубликат [Как вы обманываете коллекцию объектов сеанса с использованием Moq] (http://stackoverflow.com/questions/524457/how-do-you-mock-the-session-object-collection-using-moq) – Swati

+0

Не совсем ответ на ваш вопрос, но вам не нужно было это делать, если бы вы не нарушали лучшую практику. Вы не должны помещать объекты пользователя в сеанс, если по какой-либо другой причине этот сеанс является энергозависимым носителем данных и может уйти в любое время, когда IIS чувствует себя так. Не уверен, что такое объект пользователя, но чаще всего это достигается с помощью обычного IIdentity и IPrincipal. –

ответ

3

Я использую этот подход:

var controller = new HomeController(); 
var context = MockRepository.GenerateStub<ControllerContext>(); 
context.Expect(x => x.HttpContext.Session["MyKey"]).Return("MyValue"); 
controller.ControllerContext = context; 

См ScottGu'S blog post.

0

Уже ответил здесь. How do you mock the session object collection using Moq

Другим вариантом является наличие адаптера ISession, который позволяет вам издеваться над этим, когда ваш контейнер IOC вводит его в сервис.

Нечто подобное.

container.Register(Component.For<HttpSessionStateBase>() 
     .LifeStyle.PerWebRequest 
     .UsingFactoryMethod(() => new HttpSessionStateWrapper(HttpContext.Current.Session))); 
0

Вот мое решение для этого в MVC5, используя POCO, издеваясь над библиотекой, такой как Moq.

  HttpContext.Current = MockHttpContext.FakeHttpContext(true, "[email protected]", true, "http://somesite.com/Path/To"); 
      var httpContextBase = new HttpContextWrapper(HttpContext.Current); 
      InternalController controller = new InternalController(); 
      RouteData route_data = new RouteData(); 
      ControllerContext controller_context = new ControllerContext(httpContextBase, route_data, controller); 
      controller.ControllerContext = controller_context; 

Вышеприведенные устанавливает контроллер MVC, а затем я протестировать Посмотреть вызов так:

var result = controller.SomeMethod(somevar) as ViewResult; 

А потом утверждать на результат каких-либо модели биты, которые он содержит.

Мой FakeHttpContext.cs класс:

public static HttpContext FakeHttpContext(bool login = true, string user = "[email protected]", bool add_role = true, string url = "http://tempuri.org/") 
    { 
     if(add_role) 
     { 
      MockRoleProvider mock = Roles.Provider as MockRoleProvider; 
      if (mock == null) throw new NullReferenceException("MockRoleProvider null exception."); 
      mock.ClearAll(); 
      mock.CreateUser(user); 
      mock.CreateRole("User"); 
      mock.AddUsersToRoles(new string[] { user }, new string[] { "User" }); 
     } 

     var httpRequest = new HttpRequest("", url, ""); 
     var stringWriter = new StringWriter(); 
     var httpResponse = new HttpResponse(stringWriter); 
     var httpContext = new HttpContext(httpRequest, httpResponse); 

     var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(), 
               new HttpStaticObjectsCollection(), 10, true, 
               HttpCookieMode.AutoDetect, 
               SessionStateMode.InProc, false); 

     httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance, 
            null, CallingConventions.Standard, 
            new[] { typeof(HttpSessionStateContainer) }, 
            null) 
          .Invoke(new object[] { sessionContainer }); 

     if(login) 
     { 
      // User is logged in 
      httpContext.User = new GenericPrincipal(
       new GenericIdentity(user), 
       new string[0] 
       ); 
      httpContext.Session["UserID"] = user; 
     } 
     else 
     { 
      // User is logged out 
      httpContext.User = new GenericPrincipal(
       new GenericIdentity(String.Empty), 
       new string[0] 
       ); 
     } 

     return httpContext; 
    } 

Для полноты, вот мой MockRoleProvider.cs:

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; } 
    } 
} 

И, наконец, из app.config в моем единичном тестовом проекте:

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

Я также запустить членский класс и конфиг, nd Использование Усилия для обеспечения EF поддельным db. Что касается среды тестирования интеграции, которая работает точно так же, как и любой другой единичный тест, она идеально подходит для моих целей.

Смежные вопросы