使用起订量来验证的方法被称为存储库 [英] Using moq to verify a method is called in a repository

查看:90
本文介绍了使用起订量来验证的方法被称为存储库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我问<一个href=\"http://stackoverflow.com/questions/13301044/using-moq-to-verify-a-method-is-called-on-an-mvc-controller\">this质询时有关测试的控制器操作和验证,在我的仓库一个方法被调用。答案回来,我应该测试Save方法被称为中只存储库中的单独测试注册方法(无论是在同一仓库)内。这就是我想,但我来了做了测试,我无法得到它的工作。 (

下面是库​​测试,我要去哪里错了?

  [TestMethod的]
    公共无效Register_calls_Save_method_when_Member_is_valid()
    {
        _mockMemberRepository.Setup(R = GT; r.GetByEmail(It.IsAny&LT;串GT;()))返回((会员)空)。
        MembershipCreateStatus状态= _mockMemberRepository.Object.Register(_testMember.Email,密码,密码);
        _mockMemberRepository.Verify(R =&GT; r.Save(It.IsAny&所述;会员&GT;()),Times.Once());
    }

下面是对资源库中的注册方式:

 公共MembershipCreateStatus寄存器(字符串email,字符串密码,串确认)
    {
        如果(password.Equals(确认))
        {
            尝试
            {
                成员M = GetByEmail(电子邮件);
                如果(M == NULL)
                {
                    INT格式=(INT)PasswordFormatEnum.Encrypted;
                    字符串盐= GenerateSalt();
                    字符串传递= EN codePassword(密码,格式,盐);                    M =新会员()
                    {
                        电子邮件=电子邮件,
                        密码=传球,
                        PasswordSalt =盐,
                        了passwordFormat =格式
                    };
                    保存(米);
                    返回MembershipCreateStatus.Success;
                }
                其他
                    返回MembershipCreateStatus.DuplicateEmail;
                //,与该电子邮件地址的用户已存在如有需要恢复你的密码使用忘记密码的链接。
            }
            赶上(异常前)
            {
                _logger.LogError(除息);
                返回MembershipCreateStatus.ProviderError;
            }
        }
        返回MembershipCreateStatus.InvalidPassword;
    }


解决方案

您不能使用起订量来验证你从该对象的另一种方法调用一个对象上的一种方法。你可以做的是验证的东西,被称为在你保存()方法被调用。

例如,如果我写的是使用Ado.Net更新数据库我可以做类似下面的我自己的仓库:

 公共类MyRepository:IRepository {
   私人只读了IDatabase m_db;
   公共MyRepository(MYDATABASE了IDatabase){
      m_db = MyDatabase的;
   }   公共无效寄存器(字符串email,字符串密码等。){
      // ... 做东西 ...
      保存(米);
      // ... 做东西 ...
   }   公共无效保存(会员成员){
      // ...构建SQL查询...
      m_db.ExecuteNonQuery(的SqlCommand);   }
}

您会再经过一个嘲笑数据库对象到你的仓库在测试和你确认:

  [TestMethod的]
公共无效Register_calls_Save_method_when_Member_is_valid()
{
    模拟&LT;&了IDatabase GT; _mockDB =新的模拟&LT;&了IDatabase GT;();
    //设置mockDB与返回值GetByEmail()等。    _repository =新MyRepository(_mockDB.Object);    MembershipCreateStatus状态= _repository.Register(Email@Email.com,密码,密码);
    _mockDB.Verify(R =&GT; r.ExecuteNonQuery(It.IsAny&所述;的SqlCommand&GT;()),Times.Once());
}

所以,你不验证保存()显式调用,而是通过验证正确的底层数据库调用被称为可以验证保存()发生了。

同样的方法应该过其他框架工作。

I asked this question earlier about testing a controller action and verifying that a method in my repository was being called. The answer came back that I should be testing a Save method which is called inside the Register method (both in the same repository) in a seperate test on the repository only. That's what I thought, but I'm coming to do the test and I can't get it to work. :(

Here's the repository test, where am I going wrong?

    [TestMethod]
    public void Register_calls_Save_method_when_Member_is_valid()
    {
        _mockMemberRepository.Setup(r => r.GetByEmail(It.IsAny<string>())).Returns((Member)null);            
        MembershipCreateStatus status = _mockMemberRepository.Object.Register(_testMember.Email, "password", "password");
        _mockMemberRepository.Verify(r => r.Save(It.IsAny<Member>()), Times.Once());
    }

Here's the Register method on the repository:

public MembershipCreateStatus Register(string email, string password, string confirm)
    {
        if (password.Equals(confirm))
        {
            try
            {
                Member m = GetByEmail(email);
                if (m == null)
                {
                    int format = (int)PasswordFormatEnum.Encrypted;
                    string salt = GenerateSalt();
                    string pass = EncodePassword(password, format, salt);

                    m = new Member()
                    {
                        Email = email,
                        Password = pass,
                        PasswordSalt = salt,
                        PasswordFormat = format
                    };
                    Save(m);
                    return MembershipCreateStatus.Success;
                }
                else
                    return MembershipCreateStatus.DuplicateEmail;
                //"A user with that email address already exists. Please use the Forgotten Password link if you need to recover your password.";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex);
                return MembershipCreateStatus.ProviderError;
            }
        }
        return MembershipCreateStatus.InvalidPassword;
    }

解决方案

You can't use Moq to verify that you're calling one method on an object from another method on that object. What you can do is verify that something that is called in your Save() method is called.

For example, if I was writing my own repository that was using Ado.Net to update a database I could do something like the following:

public class MyRepository : IRepository {
   private readonly IDatabase m_db;
   public MyRepository(IDatabase myDatabase){
      m_db = myDatabase;
   }

   public void Register(string email, string password, etc.){
      // ... do stuff ...
      Save(m);
      // ... do stuff ...
   }

   public void Save(Member member){
      // ... build sql query ...
      m_db.ExecuteNonQuery(sqlCommand);

   }
}

You'd then pass a mocked database object to your repository in your test and you'd verify that:

[TestMethod]
public void Register_calls_Save_method_when_Member_is_valid()
{
    Mock<IDatabase> _mockDB = new Mock<IDatabase>();
    // Setup mockDB with return values for GetByEmail(), etc.

    _repository = new MyRepository(_mockDB.Object);

    MembershipCreateStatus status = _repository.Register("Email@Email.com", "password", "password");
    _mockDB.Verify(r => r.ExecuteNonQuery(It.IsAny<SqlCommand>()), Times.Once());
}

So, you're not verifying that Save() is called explicitly, but by verifying that the right underlying database call was called you can verify that Save() happened.

The same approach should work for other frameworks too.

这篇关于使用起订量来验证的方法被称为存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆