简体   繁体   中英

Mocking a MembershipUser

I'm currently developing an asp.net mvc 2 application which uses the default SqlMembershipProvider for authentication. I've implemented a controller method that reads the ProviderUserKey of the current user by calling Membership.GetUser().ProviderUserKey . Now I'm trying to write some test methods for this controller.

To get rid of the dependancy on the static Membership class, I've created a thin wrapper and made my controller depend on the corresponding interface:

public interface IStaticMembershipService {
    MembershipUser GetUser();

    void UpdateUser(MembershipUser user);
}

So far everything works, but in order to unit-test the controller, I still need to mock the GetUser() method of this interface and return a MembershipUser object that contains a ProviderUserKey property. What is the easiest way to mock such an object?

I'm using moq as mocking framework.

It'd look something like this:

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

If the MembershipUser class doesn't lend itself to mocking (ie if ProviderUserKey isn't virtual), you'll want to create your own object to represent the values you're going to need from a MembershipUser object, and have your service return one of those instead.

There's also a slight possibility that a MembershipUser is a poco-like object, and you can create an instance like this:

var userMock = new MembershipUser {ProviderUserKey = guid};

I think you need to separate your implementation specifics from the interface the consumer really cares about. I'm not sure what your control needs the ProviderUserKey for, if it's casting it to a specific class, etc., but I would look at making your interface actually meet the controller's needs, not the other way around. Something like (without knowing more details):

public interface IMembershipDetailsService {
    Guid UserKey { get; }
}

Once you do that level of abstraction, then mocking becomes much easier, because you could just do:

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

Just another thought, rather than trying to return a whole MembershipUser object you need to further stub.

Something similar to this:

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

Could you do something like below if you need to Mock out the HttpContext stuff too.. below is using NUnit and Moq .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM