Using moq to verify a method is called on an mvc controller

无人久伴 提交于 2019-12-11 20:15:22

问题


I'm testing an MVC controller and want to test that a Save method is called within one of my repositories. The controller is an AccountController which is attempting to Register a user. My AccountRepository has two methods, Save and Register. Register is calling Save after some checks. I'm not sure if I should just be testing whether Register gets called and running a seperate unit test on my Repository to verify if Save is called as part of calling Register or whether I've set up Moq incorrectly on my test.

Here's my test:

[TestMethod]
        public void register_post_saves_valid_registration()
        {
            _mockMemberRepository.Setup(r => r.GetByEmail(It.IsAny<string>())).Returns(_testMember);

        // Arrange
        RegisterViewModel model = new RegisterViewModel()
        {
            Email = "registerme@talentsite.com",
            Password = "test123",
            ConfirmPassword = "test123"
        };
        // Act
        ActionResult result = _controller.Register(model);
        // Assert
        _mockMemberRepository.Verify(r => r.Register(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once());
        _mockMemberRepository.Verify(r => r.Save(It.IsAny<Member>()), Times.Once());
    }

This line:

_mockMemberRepository.Verify(r => r.Register(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once());

passes the test, but when I introduce the line below:

_mockMemberRepository.Verify(r => r.Save(It.IsAny<Member>()), Times.Once());

it fails.

Here is my Register method in my 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;
    }

My Save method just takes a Member object and is a void method.

What am I doing wrong?


回答1:


From the above code, it seems that the Save method is part of the Register method. If that is the case, then the Register method is part of the mockRepository, so it is mocked. Thus, the real implementation, which invokes Save will never be invoked.

Assuming the above is true (which I believe is, but can't really tell because I don't have the Controller code), you need to create separate tests:

  1. The one you have right now, removing the Save verification.
  2. A unit test for the repository, and make sure that Save is invoked when Register is called.


来源:https://stackoverflow.com/questions/13301044/using-moq-to-verify-a-method-is-called-on-an-mvc-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!