【问题标题】:Unit testing Raven and ASP.NET Membership单元测试 Raven 和 ASP.NET 成员资格
【发布时间】:2011-07-07 16:41:08
【问题描述】:

我正在启动一个 Web 应用程序,它将使用 asp.net 会员服务(带有 sql server 后端)来照顾用户和 RavenDb 的其他一切。

我是单元测试的新手,如果我能用一个示例方法跑过你到目前为止我所拥有的东西,我将不胜感激。

这是螺旋管理器

public class HelixManager:IDisposable
{
    private readonly IMembershipProvider _membership;
    private readonly IRepository _repos;

    public HelixManager()
    {
        _membership = new AspNetMembershipProvider(); 
        _repos = new RavenRepository();
    }

    public HelixManager(IMembershipProvider membershipProvider, IRepository repos) 
    { 
        _membership = membershipProvider;
        _repos = repos;
    }

    public User CreateAdmin(User newUser, string password)
    {
        if (String.IsNullOrEmpty(newUser.Email)) throw new ArgumentException("Email must be supplied");
        if (String.IsNullOrEmpty(password)) throw new ArgumentException("Password must be supplied");

        var memberId = _membership.CreateUser(newUser, password);

        if (memberId != null)
        {
            _membership.AddToRole(newUser, "Admin");

            newUser.Type = UserType.Admin;
            newUser.MemberId = memberId;

            _repos.Store<User>(newUser);
        }

        return newUser;
    }

这是 IMembershipProvider

public interface IMembershipProvider
{
    string CreateUser(User newUser, string password);
    void AddToRole(User user, string rolename);
}

和 AspNetMembershipProvider 的实现

public class AspNetMembershipProvider : IMembershipProvider
{
    public string CreateUser(User newUser, string password)
    {
        MembershipCreateStatus status;
        MembershipUser memUser = System.Web.Security.Membership.CreateUser(newUser.Email, password, newUser.Email, "", "", true, out status);
        return memUser.ProviderUserKey.ToString();
    }

    public void AddToRole(User user, string role)
    {
        Roles.AddUserToRole(user.Email, role);
    }
}

这是 IRepository

public interface IRepository
{
    T Store<T>(T item);
}

它的实现

public class RavenRepository : IRepository
{
    private readonly DocumentStore _store;

    public RavenRepository()
    {
        _store = new DocumentStore { DefaultDatabase = "Helix", Url = "http://localhost:8080" };
        _store.Initialize();
    }

    public T Store<T>(T item)
    {
        using (var session = _store.OpenSession())
        {
            session.Store(item);
            session.SaveChanges();
        }
        return item;
    }
}

在我的测试项目中,我创建了这两个的假实现:

FakeMembershipProvider:

class FakeMembershipProvider : IMembershipProvider
{
    public string CreateUser(User newUser, string password)
    {
        CreatedUser = true;
        return newUser.Email == "email@example.com" ? Guid.NewGuid().ToString() : null;
    }

    public void AddToRole(User user, string rolename)
    {
        AddedToRole = true;
    }

    public bool AddedToRole;
    public bool CreatedUser;
}

和 FakeRepository:

public class FakeRepository : IRepository
{
    public T Store<T>(T item)
    {
        StoreCalled = true;
        return item;
    }

    public bool StoreCalled;
}

测试大致如下:

public class UserManagementTests
{
    private readonly HelixManager _hm;
    private readonly IMembershipProvider _fakeMembershipProvider;
    private readonly IRepository _fakeRepository;

    public UserManagementTests()
    {
        _fakeMembershipProvider = new FakeMembershipProvider();
        _fakeRepository = new FakeRepository();
        _hm = new HelixManager(_fakeMembershipProvider, _fakeRepository);       
    }

    [TestMethod]
    public void CreateAdminReturnsValidAdminUser()
    {

        var newUser = new User
                           {
                               AvatarName = "fred",
                               Email = "email@example.com",
                               Forename = "Fred",
                               Surname = "Jones"
                           };

        _hm.CreateAdmin(newUser, "password");

        Assert.IsNotNull(newUser.MemberId);
        Assert.AreEqual(UserType.Admin, newUser.Type);
    }

我要问的是,在我进一步了解这条线之前,这是解决这个问题的正确方法吗?或者有更好的方法吗?

我还计划创建一个 IntegrationTests 项目,该项目将使用一个真实的数据库和一个真实的 RavenDb 实例进行端到端测试。

干杯,

戴夫

【问题讨论】:

    标签: asp.net unit-testing ravendb


    【解决方案1】:

    我认为这种方法没有任何问题。您可以使用 Mocking 工具(Rhino MocksMoqNSubstitute)来创建您的假货,而不是手工制作,但这实际上是个人喜好和个人舒适度的问题工具。

    您的测试结构清晰,基于状态断言(这是一件好事),并且您没有尝试一次测试太多东西,这是一个常见的错误(即使对于我们这些一直这样做的人来说)一会儿)。

    如果你还没有看过,我强烈推荐Roy Osherove'sArt of Unit Testing,它有很多关于单元测试的非常好的信息,包括保持测试干净、如何处理不易测试的区域代码等。

    我说保持卡车运 :)

    【讨论】:

    • 感谢您的回复!订书。 :)
    【解决方案2】:

    你的测试在我看来绝对没问题。正确的方法(模拟)正确的方法(AAA)。

    继续吧:)

    【讨论】:

    • 感谢您的回复和支持。 :)
    【解决方案3】:

    我的问题实际上是这样的:

    我正在启动一个网络应用程序,它将是 使用 asp.net 会员服务 (带有 sql server 后端)查看 在用户和 RavenDb 之后 否则。

    你为什么要这样做? 在 RavenDB 中制作一切会更容易,并且您的单元测试问题就像 new EmbeddableDocumentStore { RunInMemory = true }

    一样简单

    【讨论】:

    • 我们使用会员服务是因为我们已经习惯了,而且我们对它的工作方式很满意(而且我们已经有一个可用的 SQL 服务器)但是 EmbeddableDocumentStore 的建议对于ravendb 位! :)
    • +!对于 Ayende 的回答。避免像瘟疫一样的 ASP.NET MEMBERSHIP!做。不是。采用。设计的太恶心了您可以非常简单地推出自己的产品,并且不必使用 Sql Server。 RavenDB 可以轻松处理用户管理。
    猜你喜欢
    • 2015-03-03
    • 2012-03-02
    • 2010-11-04
    • 2013-06-27
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多