使用moq验证在存储库中调用的方法

时间:2012-11-09 02:40:06

标签: asp.net asp.net-mvc c#-4.0 moq

我问this question earlier有关测试控制器操作并验证我的存储库中的方法是否被调用的问题。答案回来了,我应该测试一个Save方法,该方法在Register方法中调用(在同一个存储库中),仅在存储库中进行单独测试。这就是我的想法,但我来做测试,我无法让它工作。 :(

这是存储库测试,我哪里错了?

    [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());
    }

这是存储库中的Register方法:

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;
    }

1 个答案:

答案 0 :(得分:1)

您不能使用Moq来验证您是否正在从该对象上的另一个方法调用对象上的一个方法。你可以做的是验证你的Save()方法中调用的东西是否被调用。

例如,如果我正在编写自己的存储库,使用Ado.Net来更新数据库,我可以执行以下操作:

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);

   }
}

然后,您将测试中的模拟数据库对象传递到存储库,并验证:

[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());
}

因此,您没有验证是否显式调用了Save(),但通过验证是否已调用正确的基础数据库调用,您可以验证Save()是否已发生。

同样的方法也适用于其他框架。