使用Moq模拟返回void的更新方法

87
在我的测试中,我定义了一个带有一些记录的List<IUser>作为数据。
我想设置一个moq方法Update,该方法接收要更新的用户idstring
然后我获取IUser并更新属性LastName
我尝试了这个:
namespace Tests.UnitTests
{
    [TestClass]
    public class UsersTest
    {
        public IUsers MockUsersRepo;
        readonly Mock<IUsers> _mockUserRepo = new Mock<IUsers>();
        private List<IUser> _users = new List<IUser>();

        [TestInitialize()]
        public void MyTestInitialize()
        {
            _users = new List<IUser>
                {
                    new User { Id = 1, Firsname = "A", Lastname = "AA", IsValid = true },
                    new User { Id = 1, Firsname = "B", Lastname = "BB", IsValid = true }
                };

            Mock<IAction> mockUserRepository = new Mock<IAction>();
            _mockUserRepo.Setup(mr => mr.Update(It.IsAny<int>(), It.IsAny<string>()))
                .Returns(???);

            MockUsersRepo = _mockUserRepo.Object;
        }

        [TestMethod]
        public void Update()
        {
            //Use the mock here
        }

    }
}

但是我遇到了这个错误:无法解析Returns符号

你有一个id吗?

class User : IUser
{
    public int Id { get; set; }
    public string Firsname { get; set; }
    public string Lastname { get; set; }
    public bool IsValid { get; set; }
}

interface IUser
{
    int Id { get; set; }
    string Firsname { get; set; }
    string Lastname { get; set; }
    bool IsValid { get; set; }
}

interface IAction
{
    List<IUser> GetList(bool isActive);
    void Update(int id, string lastname)
}

class Action : IAction
{
    public IUser GetById(int id)
    {
        //....
    }
    public void Update(int id, string lastname)
    {
        var userToUpdate = GetById(id);
        userToUpdate.LastName = lastname;
        //....
    }
}

1
你想要测试什么? - Davin Tryon
@Kris-I 目前无法通过您的公共接口进行检查。您可能希望从该方法中返回更新后的用户或姓氏。 - Ufuk Hacıoğulları
@UfukHacıoğulları 好的,我会将方法更改为返回更新后的用户,请您更新您的答案吗? - TheBoubou
@Kris-I 请发布您更新后的IUsers接口。我在您的代码中没有看到它。IAction是否继承它? - Ufuk Hacıoğulları
@UfukHacıoğulları,我的错误,应该是IAction而不是IUsers。 - TheBoubou
显示剩余3条评论
2个回答

138

如果您只想验证该方法是否被调用,那么您应该使用Verifiable()方法。

_mockUserRepository.Setup(mr => mr.Update(It.IsAny<int>(), It.IsAny<string>()))
                   .Verifiable();

如果您也想对这些参数进行操作,请先使用Callback()。

_mockUserRepository.Setup(mr => mr.Update(It.IsAny<int>(), It.IsAny<string>()))
                   .Callback((int id, string lastName) => {
                       //do something
                       }).Verifiable();

更新

如果您的函数返回一个布尔值作为结果,这是如何模拟它的。

_mockUserRepository.Setup(mr => mr.Update(It.IsAny<int>(), It.IsAny<string>()))
                   .Returns(true);

1
@Kris-I 我猜你在模拟的类中保留了 List<IUser>。如果是这样,你不应该关心被模拟类的实现。你应该测试使用存储库的类。 - Ufuk Hacıoğulları
1
@Kris-I 你试图模拟你正在测试的类。你应该模拟它的依赖关系。我认为阅读这篇文章可能会有所帮助:http://www.kaczanowscy.pl/tomek/2011-01/testing-basics-sut-and-docs - Ufuk Hacıoğulları
如果您只想让它返回而不运行基础方法,该怎么办呢? 那么我就不需要它是可验证的了吗? - f1wade
@f1wade 你所说的基础方法是什么意思? - Ufuk Hacıoğulları
@f1wade 你可以创建一个严格行为的模拟对象。如果你没有设置任何内容,当调用模拟对象上的方法时,它将抛出异常。 - Ufuk Hacıoğulları
显示剩余11条评论

23
Mock<IUsers> _mockUserRepository = new Mock<IUsers>();
        _mockUserRepository.Setup(mr => mr.Update(It.IsAny<int>(), It.IsAny<string>()))
                            .Callback((int id, string name) =>
                                {
                                    //Your callback method here
                                });
 //check to see how many times the method was called
 _mockUserRepository.Verify(mr => mr.Update(It.IsAny<int>(), It.IsAny<string>()), Times.Once());

12
希望这段代码有一些相关的细节说明!会更有帮助。 - Farax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接