【问题标题】:Unit test and moq work shows exception as: The following setups were not matched:单元测试和起订量工作显示异常为:以下设置不匹配:
【发布时间】:2013-12-17 17:03:09
【问题描述】:

我正在使用最小起订量,但 verifyAll 方法调用失败。我不知道我做错了什么。

要测试的类:

namespace ConsoleApplication2
{
    public class SomeUtil
    {
        public static List<Person> underAgePerson = new List<Person>();

        public static List<Person> females = new List<Person>();

        public static List<Person> males = new List<Person>();

        public static List<Person> deletePersons = new List<Person>();

        public SomeAdapter adapter;

        public SomeUtil()
        {
            this.adapter = new SomeAdapter();
        }

        public void Valid(List<Person> persons)
        {
            foreach (Person p in persons)
            {
                if (p.Name == null)
                {
                    deletePersons.Add(p);
                }

                if (p.Age < 18)
                {
                    if (!deletePersons.Contains(p))
                    {
                        deletePersons.Add(p);
                    }
                    underAgePerson.Add(p);
                }
                adapter.SetGender(p);
                if (p.Gender.Equals("Male", StringComparison.InvariantCultureIgnoreCase))
                {
                    males.Add(p);
                }

                else if (p.Gender.Equals("Female", StringComparison.InvariantCultureIgnoreCase))
                {
                    females.Add(p);
                }
            }

            foreach (Person p in deletePersons)
            {
                persons.Remove(p);
            }
            deletePersons.Clear();
        }
    }
}

SomeUtil 类:

namespace ConsoleApplication2
{
    public class SomeAdapter
    {
        public virtual Person SetGender(Person p)
        {
            if (string.IsNullOrEmpty(p.Gender))
            {
                p.Gender = "Male";
            }
            return p;
        }
    }
}

单元测试:

[TestClass]
public class SomeUtilTest
{
    Mock<SomeAdapter> adapter;
    List<Person> persons;
    SomeUtil util;
    [TestInitialize]
    public void Initialize()
    {
        adapter = new Mock<SomeAdapter>();
        persons = new List<Person>();
        util = new SomeUtil();
    }

    [TestCleanup]
    public void CleanUp()
    {
        adapter.VerifyAll();
    }

    [TestMethod]
    public void Valid_WithEmptyName_ShouldRemove()
    {
        Person person = new Person();
        person.Gender = "";
        person.Age = 1;
        persons.Add(person);

        Person result = new Person();
        result.Age = 19;
        result.Gender = "Female";
        result.Name = "Dannie";

        adapter.Setup(a => a.SetGender(person)).Returns(result);
        int count = persons.Count;
        util.Valid(persons);

        Assert.AreEqual(count - 1, persons.Count);

    }
}

【问题讨论】:

    标签: c# visual-studio-2012 moq


    【解决方案1】:

    这是因为您的 SomeUtil 类使用的是真正的 SomeAdapter 类,而不是 Mock 类。 Moq 无法观察真实类中方法的使用情况。

    您需要做的是将 SomeAdapter 的实例注入到您的 SomeUtil 类中。而不是:

        public SomeAdapter adapter;
        public SomeUtil()
        {
            this.adapter = new SomeAdapter();
        }
    

    这样做:

        public SomeAdapter adapter;
        public SomeUtil(SomeAdapter adapter)
        {
            this.adapter = adapter;
        }
    

    那么,在单元测试中:

        [TestInitialize]
        public void Initialize()
        {
            adapter = new Mock<SomeAdapter>();
            persons = new List<Person>();
            util = new SomeUtil(adapter.Object);
        }
    

    注意adapter.Object 的使用。这为您提供了 Moq 观察到的类的实例。

    如果您进行了这些更改,您的单元测试将通过。但是dependency inversion 这里有一个更深层次的基本原则,我鼓励你研究一下。在许多方面,它使使用模拟测试库变得更容易使用。

    【讨论】:

    • 干得好,给出了与我完全相同的答案,只是我忘记传入 Mock.Object。很好的答案窃取。
    • 抱歉刚刚注意到您同时发帖,以为这只是一个副本/过去稍作改编工作。先生,我收回它,并会投票给你:)
    • 你确实打败了我。我应该更快地输入它。 :) 我赞成你的回答。
    【解决方案2】:
        public SomeUtil()
        {
            this.adapter = new SomeAdapter();
        }
    

    因为你已经新建了 SomeAdapter 并且没有注入到 SomeUtil 类中,所以你正在验证的模拟不是在代码中与之交互的实例,它是一个完全不同的对象。

    您需要通过构造函数或属性注入以某种方式注入 SomeAdapter 依赖项。您可以手动执行此操作,即

    在 SomeUtil.cs 中

        public SomeUtil(SomeAdaptor adaptor)
        {
            this.adapter = adaptor;
        }
    

    在测试设置中:

        [TestInitialize]
        public void Initialize()
        {
            adapter = new Mock<SomeAdapter>();
            persons = new List<Person>();
            util = new SomeUtil(adapter.Object);
        }
    

    然而,理想情况下,您不会模拟和注入一个实体类,而是一个接口或抽象类型。此外,在您的应用程序(不是测试)中,您可能希望使用像 Ninject 或 Windsor 这样的 DI 框架(自从我使用 .NET 以来已经有一段时间了,所以现在可能有不同的选择)。

    克里斯

    【讨论】:

    • 欧文,这不会编译。 Mock 不能直接转换为 SomeAdapter。
    • 对不起,我说自从我使用 .NET 以来已经有一段时间了,而不是直接传递 Mock 您需要根据 github.com/Moq/moq4 传递 Mock.Object,生病了立即编辑
    猜你喜欢
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 2021-12-14
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多