【问题标题】:Mocking a MembershipUser模拟 MembershipUser
【发布时间】:2010-11-23 15:37:51
【问题描述】:

我目前正在开发一个使用默认 SqlMembershipProvider 进行身份验证的 asp.net mvc 2 应用程序。我已经实现了一个控制器方法,它通过调用Membership.GetUser().ProviderUserKey 来读取当前用户的ProviderUserKey。 现在我正在尝试为这个控制器编写一些测试方法。

为了摆脱对静态 Membership 类的依赖,我创建了一个瘦包装器并使我的控​​制器依赖于相应的接口:

public interface IStaticMembershipService {
    MembershipUser GetUser();

    void UpdateUser(MembershipUser user);
}

到目前为止一切正常,但为了对控制器进行单元测试,我仍然需要模拟此接口的 GetUser() 方法并返回一个包含 ProviderUserKey 属性的 MembershipUser 对象。模拟此类对象的最简单方法是什么?

我使用 moq 作为模拟框架。

【问题讨论】:

    标签: c# unit-testing asp.net-mvc-2 mocking asp.net-membership


    【解决方案1】:

    看起来像这样:

    var membershipMock = new Mock<IStaticMembershipService>();
    var userMock = new Mock<MembershipUser>();
    userMock.Setup(u => u.ProviderUserKey).Returns(guid);
    membershipMock.Setup(s => s.GetUser()).Returns(userMock.Object);
    

    如果 MembershipUser 类不适合模拟(即,如果 ProviderUserKey 不是虚拟的),您将需要创建自己的对象来表示您需要从 MembershipUser 对象中获得的值,并拥有您的服务会返回其中之一。

    MembershipUser 也有可能是类似 poco 的对象,您可以像这样创建一个实例:

    var userMock = new MembershipUser {ProviderUserKey = guid};
    

    【讨论】:

    • 非常感谢,创建 MembershipUser 类的模拟效果很好。
    【解决方案2】:

    我认为您需要将您的实现细节与消费者真正关心的接口分开。我不确定您的控件需要 ProviderUserKey 来做什么,是否将其转换为特定的类等,但我会着眼于让您的界面真正满足控制器的需求,而不是相反。类似的东西(不知道更多细节):

    public interface IMembershipDetailsService {
        Guid UserKey { get; }
    }
    

    一旦你做了那个级别的抽象,那么模拟就变得容易多了,因为你可以这样做:

    membershipService.Setup (svc => svc.UserKey).Returns (myGuid);
    

    只是另一个想法,而不是尝试返回整个 MembershipUser 对象,您需要进一步存根。

    【讨论】:

      【解决方案3】:

      类似的东西:

      var user = new MembershipUser();
      var membershipService = new Mock<IStaticMembershipService>();
      membershipService.Setup(p => p.GetUser()).Returns(user);
      

      【讨论】:

        【解决方案4】:

        如果你也需要模拟出 HttpContext 的东西,你能做下面这样的事情吗?下面是使用 NUnitMoq

        [SetUp]
        private void Setup()
        {
            _mockHttpContext = new Mock<HttpContextBase>();
            _mockStaticMembership = new Mock<IStaticMembershipService>();           
            _mockUser = new Mock<MembershipUser>();
            _mockPrincipalUser = new Mock<IPrincipal>();        
        
            _mockHttpContext.Setup(http => http.User).Returns( _mockPrincipalUser.Object );
            _mockPrincipalUser.Setup(principal => principal.Identity.Name).Returns("myname");
            _mockUser.Setup(user => user.ProviderUserKey).Returns( Guid.NewGuid() );
        
            _mockStaticMembership.Setup(membership => membership.GetUser(It.IsAny<string>())).Returns( _mockUser.Object );
        
        }
        
        [Test]
        public void Some_Test_For_My_Controller()
        {            
            var controller = new MyController( _mockStaticMembership.Object );            
            controller.ControllerContext = new ControllerContext(_mockHttpContext.Object, new RouteData(), controller);
        
            //Test your action and verify   
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-29
          • 2010-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多