使用Moq验证方法在MVC控制器上被调用 [英] Using moq to verify a method is called on an mvc controller

查看:85
本文介绍了使用Moq验证方法在MVC控制器上被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试MVC控制器,并且想测试在我的一个存储库中是否调用了Save方法.该控制器是一个AccountController,它正在尝试注册用户.我的AccountRepository有两种方法,保存和注册.经过一些检查后,注册人员正在调用保存.我不确定是否应该只是测试是否调用了Register并在我的存储库上运行单独的单元测试,以验证是否在调用Register的过程中调用了Save,或者我是否在测试中设置了不正确的Moq.

这是我的考试:

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

此行:

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

失败.

这是我的存储库中的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;
    }

我的Save方法仅接受一个Member对象,并且是一个无效方法.

我在做什么错了?

解决方案

从上面的代码看来,Save方法是Register方法的一部分.如果是这种情况,那么Register方法是mockRepository的一部分,因此将被模拟.因此,调用Save的实际实现将永远不会被调用.

假设以上内容是正确的(我相信是正确的,但由于我没有Controller代码,所以无法真正分辨出来),您需要创建单独的测试:

  1. 您现在拥有的那个,删除保存"验证.
  2. 对存储库的单元测试,并确保在调用Register时调用Save.

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?

解决方案

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.

这篇关于使用Moq验证方法在MVC控制器上被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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