Moq - 如何验证方法调用哪个参数已被清理(列表)

时间:2012-02-13 20:30:36

标签: unit-testing moq

我已经获得了以下代码,我需要帮助才能为其编写单元测试。我正在使用Moq库。

这是这笔交易。我有一个业务类与存储库(接口)的依赖关系,所以我可以用它来保存我的实体到数据库。我的实体基本上是一个字符串列表。来自MyBusinessClass的AddAndSave方法获取它作为参数接收的值,将其放入列表并从IRepository调用Save方法。然后,我清除我的实体列表。下面的代码显示了这个例子(我已经简单了,所以我可以在这里解释一下)。

也有单元测试。

using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace TestesGerais
{
    public class MyEntity
    {
        public MyEntity()
        {
            MyList = new List<string>();
        }
        public List<string> MyList { get; set; }
    }

    public interface IRepository
    {
        void Save(MyEntity entity);
    }

    public class MyBusinessClass
    {
        public IRepository Repository { get; set; }
        private MyEntity _entity = new MyEntity();
        public void AddAndSave(string info)
        {
            _entity.MyList.Add(info);
            Repository.Save(_entity);
            _entity.MyList.Clear();  // for some reason I need to clear it
        }
    }

    [TestClass]
    public class UnitTest10
    {
        [TestMethod]
        public void TestMethod1()
        {
            var mock = new Mock<IRepository>();
            MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
            b.AddAndSave("xpto");
            mock.Verify(m => m.Save(It.Is<MyEntity>(x => x.MyList[0] == "xpto")), Times.Exactly(1));
        }
    }
}

我的单元测试检查是否调用了IRepository的Save方法,其参数(实体)在列表中有一个元素,并且值为&#34; xpto&#34;在这个元素中。

当我运行此测试时,它会变为红色,并显示错误消息&#34;测试方法TestesGerais.UnitTest10.TestMethod1引发异常: System.ArgumentOutOfRangeException:索引超出范围。必须是非负数且小于集合的大小。 参数名称:index&#34;。

好的,这是由已清理的列表引起的。如果我评论该行&#34; _entity.MyList.Clear();&#34;,一切顺利。

我的问题是:如何在不评论&#34; Clear&#34;在我的业务类中行,并确保调用我的存储库方法传递特定值(实体包含一个元素值为#34; xpto&#34;)?

由于

2 个答案:

答案 0 :(得分:1)

我使用Moq的Callback功能更改了单元测试。这样,我可以设置mock,这样当调用AddAndSave时,它接收的参数将保存到我单元测试的变量中,我可以稍后断言。

    [TestMethod]
    public void TestMethod1()
    {
        var mock = new Mock<IRepository>();
        string result = string.Empty;
        mock.Setup(m => m.Save(It.IsAny<MyEntity>())).Callback((MyEntity e) => { result = e.MyList[0]; });
        MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
        b.AddAndSave("xpto");
        Assert.AreEqual(result, "xpto");
    }

答案 1 :(得分:0)

你可以将你的方法分开一点。 “AddAndSave”并不是全部。然后,您可以单独测试添加和保存位的行为。