Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET - Unit test MembershipProvider

I'm trying to unit test the MembershipProvider, however I cant figure out how or whether there is any need for unit testing of it...

My business layer:

public interface IAccountService
{
    MembershipCreateStatus CreateUser(string userName, string password, string email);
}

public class AccountService : IAccountService
{
    private readonly MembershipProvider provider;

    public AccountService() : this(null) { }
    public AccountService(MembershipProvider providera)
    {
        this.provider = providera ?? Membership.Provider;
    }

    public MembershipCreateStatus CreateUser(string userName, string password, string email)
    {
        if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", userName);
        if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", password);
        if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", email);

        MembershipCreateStatus status;
        provider.CreateUser(userName, password, email, null, null, true, null, out status);

        return status;
    }
}

The only examples I've found so far requires a "MockMembershipProvider" with a local database setup... seems quite odd to me.

Thanks in advance.

like image 443
ebb Avatar asked Nov 21 '10 12:11

ebb


Video Answer


1 Answers

Having a "MockMembershipProvider with a local database setup" is odd for a few reasons.

Typically you do not want to unit test data access code. Your unit tests should run very quick, and be run often, and thus not require database access. This is why you should be able to mock your data access tier. Persisting data would be acceptable for integration testing, but typically not unit testing.

The rest of this answer is based on the assumption that you do not want to hit the DB in your unit test.


Whether you wish to unit test the membership provider will depend on what is going on in there.

  1. If the membership provider is custom written and contains business logic then it should be unit tested. If this is the case you need to create a mock DAO object within the membership provider so that the membership provider can be exercised by unit tests without hitting the database.

  2. If the membership provider is simply carrying out database access (either directly or with call forwarding to the data access tier), you should not unit test it. If you are using the Microsoft asp.net membership provider you also should not test it.

    Instead you should create a mock MembershipProvider to use within the AccountService class. You will inject the mock using constructor injection, this is the purpose of the following boilerplate code

    public AccountService() : this(null) { }
    public AccountService(MembershipProvider providera)
    {
        this.provider = providera ?? Membership.Provider;
    }
    

    This code facilitates constructor injection of alternative implementations (which includes mocks). An example of what a test might look like:

        [Test]
        public void ExampleTestWithAHandRolledMock()
        {
            //arrange
            var mockMembershipProvider = new MockMembershipProvider();//no db access in this mock implementation
            var accountService = new AccountService(mockMembershipProvider);
            //act
            accountService.CreateUser("foo", "bar", "baz");
            //assert
            Assert.IsTrue(mockMembershipProvider.MockUserExists("foo","bar","baz");//added a method to mock to confirm user was added
        }
    
like image 198
danielfishr Avatar answered Sep 21 '22 19:09

danielfishr