ASP.NET - 单元测试MembershipProvider

ebb*_*ebb 6 c# asp.net testing unit-testing

我正在尝试对MembershipProvider进行单元测试,但是我无法弄清楚如何或是否需要对它进行单元测试......

我的业务层:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止我发现的唯一例子需要一个带有本地数据库设置的"MockMembershipProvider"......对我来说似乎很奇怪.

提前致谢.

dan*_*shr 6

由于一些原因,拥有"具有本地数据库设置的MockMembershipProvider"是奇怪的.

通常,您不希望单元测试数据访问代码.您的单元测试应该运行得非常快,并且经常运行,因此不需要数据库访问.这就是您应该能够模拟数据访问层的原因.持久化数据对于集成测试是可接受的,但通常不是单元测试.

本答案的其余部分基于您不希望在单元测试中命中数据库的假设.


您是否希望对会员提供商进行单元测试将取决于那里发生的事情.

  1. 如果成员资格提供程序是自定义编写的并包含业务逻辑,则应对其进行单元测试.如果是这种情况,您需要在成员资格提供程序中创建一个模拟DAO对象,以便可以通过单元测试来执行成员资格提供程序,而无需访问数据库.

  2. 如果成员资格提供者只是简单地执行数据库访问(直接或通过呼叫转发到数据访问层),则不应对其进行单元测试.如果您使用的是Microsoft asp.net成员资格提供程序,则也不应对其进行测试.

    相反,您应该创建一个MembershipProviderAccountService类中使用的模拟.您将使用构造函数注入注入模拟,这是以下样板代码的目的

    public AccountService() : this(null) { }
    public AccountService(MembershipProvider providera)
    {
        this.provider = providera ?? Membership.Provider;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    此代码有助于构造函数注入替代实现(包括模拟).测试可能的样子:

        [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
        }
    
    Run Code Online (Sandbox Code Playgroud)