繁体   English   中英

如何在使用Membership时测试ASP.NET MVC 3身份验证

[英]How to test ASP.NET MVC 3 authentication when using Membership

我想测试我的AccountController 问题是在Register方法中我使用下一行来创建用户:

Membership.CreateUser(model.Email, model.Password, model.Email, null, null, true, null, out createStatus);

在Web应用程序中,我使用了我使用web.config设置的CustomMembershipProvider 在我的单元测试标准SqlMembershipProvider Membership类中。 而不是我在我的应用程序中使用的CustomMembershipProvider

如何在单元测试环境中设置成员资格? 我的意思是以编程方式设置它,因为asp net在读取web.config文件后设置它。

我已经使用接口来模拟用户管理数据层,但我在想是否有办法在这种情况下避免接口。 能够在单元测试中设置成员资格的模拟实现。

public void RegisterTest()
{
    IUsersManager repository = new Tests.Data.UsersManager();
    AccountController target = new AccountController(repository); 
    //be able to set Membership underlying provider
    Membership.Provider = new MockMembershipProvider();
}

定义成员资格界面,如下所示:

public interface IMembershipProvider
{
    void CreateUser(string username, string password);
}

...为您的MVC应用程序实现它,如下所示:

public class AspDotNetMembershipProvider : IMembershipProvider
{
    public void CreateUser(string username, string password)
    {
        string createStatus;

        Membership.CreateUser(
            username,
            password,
            username,
            null,
            null,
            true,
            null,
            out createStatus);

        // throw an exception if createStatus isn't as expected
    }
}

...然后将其注入您的控制器并像这样使用它:

public class AccountController
{
    private readonly IMembershipProvider _membershipProvider;

    public AccountController(IMembershipProvider membershipProvider)
    {
        this._membershipProvider = membershipProvider;
    }

    public ActionResult Register(RegistrationModel model)
    {
        // Try and catch this, returning a success ActionResult if it worked:
        this._membershipProvider.CreateUser(model.Email, model.Password);
    }
}

ASP.NET使用像Membership这样的静态类Membership许多事情,但静态类访问总是使单元测试变得困难。 标准解决方案是为服务定义接口,使用静态ASP.NET类实现它,并将其注入控制器。

您可以使用默认的DependencyResolver和像Unity这样的DI容器来设置注入(如果您还没有)。

我已经创建了一个更加结构化的成员资格提供程序,它已被分解为三个不同的接口(并且提供程序使用DependencyResolver解析它们)。

它使得提供者的单元测试变得容易。 只需测试您的IAccountRepository实现。

你可以在这里阅读: http//blog.gauffin.org/2011/09/a-more-structured-membershipprovider/

或者只是安装nuget包:

install-package griffin.mvccontrib

您对控制器的单元测试不应使用CustomMembershipProvider或标准SQL提供程序。 如果执行单元测试,您应该使用Stub / Fake,您可以完全控制它返回的内容。 如果您在测试中使用真正的提供程序,它不再是单元测试,它是一个集成测试。

为了实现单元可测试性,您需要定义一个假提供程序,使用模拟框架或手动滚动带有“固定”结果的假冒。 假货看起来像这样:

public class FakeMembershipProvider : MembershipProvider
{
   public MembershipCreateStatus CreateStatus = MembershipCreateStatus.Success;

   public void CreateUser((string username, string password, string email, 
       string passwordQuestion, string passwordAnswer, bool isApproved, 
       object providerUserKey, out MembershipCreateStatus status)
   {
      status = CreateStatus;
   }

   ...
}

让控制器将提供者作为ctor参数

public class AccountController
{
    private readonly MembershipProvider _membershipProvider;

    public AccountController(MembershipProvider membershipProvider)
    {
        _membershipProvider = membershipProvider;
    }

    public ActionResult Register(RegistrationModel model)
    {
        MembershipCreateStatus result;
        _membershipProvider.CreateUser(model.Email, model.Password, ..., out result);

        return View(/*Make this depend on the result*/);
    }
}

在单元测试中,您希望根据要测试的内容设置假冒,并且可以断言您对每个注册结果的期望结果:

[Test]
void Should_display_success_view_when_user_successfully_created()
{
    var membershipProvider = new FakeMembershipProvider();
    membershipProvider.CreateStatus = MembershipCreateStatus.Success;
    var controller = new AccountController(membershipProvider);
    var model = new RegistrationModel();

    var result = controller.Register(model) as ViewResult;

    Assert.That(result.Name, Is.EqualTo("ExpectedViewName"));     
}

由于MemberShipProvider非常庞大并且您可能不会全部使用它,因此使用@SteveWilkes包装Membership类来创建更小的更具针对性的接口是明智的。 另外一个模拟框架可以为您节省大量工作。 为了使用新的依赖关系连接控制器,您必须创建一个新的ControllerFactory。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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