【问题标题】:Using Verify to confirm expected parameter values in Moq mock class使用验证确认 Moq 模拟类中的预期参数值
【发布时间】:2012-01-16 17:16:07
【问题描述】:

我正在尝试验证模拟中的方法是否使用预期的对象参数调用。我正在使用 Moq、nUnit,并认为 AutoFixture 的 Likeness 应该可以完成工作。 下面是我正在尝试做的简化版本。

有没有办法用 AutoFixture 做到这一点?有没有更好的方法来验证 Something 是否使用适当的参数调用?

覆盖A 类中的Equals 以比较属性值并将Verify 行更改为:

barMock.Verify(m => m.Something(a));

通过,但是我不想在我的项目中像 A 这样的每个类中覆盖 Equals。

namespace Test
{
    using Moq;
    using NUnit.Framework;
    using Ploeh.SemanticComparison.Fluent;

    public class A
    {
        public int P1 { get; set; }
    }
    public interface IBar
    {
        void Something(A a);
    }

    public class Foo
    {
        public A Data { get; private set; }
        public void DoSomethingWith(IBar bar)
        {
            Data = new A { P1 = 1 };
            bar.Something(Data);
        }
    }

    [TestFixture]
    public class AutoFixtureTest
    {
        [Test]
        public void TestSample()
        {
            var foo = new Foo();
            var barMock = new Mock<IBar>();
            var a = new A { P1 = 1 };
            var expectedA = a.AsSource().OfLikeness<A>();

            foo.DoSomethingWith(barMock.Object);

            expectedA.ShouldEqual(foo.Data);   // passes
            barMock.Verify(m => m.Something(expectedA.Value));  // fails
        }
    }
}

【问题讨论】:

    标签: nunit moq autofixture


    【解决方案1】:

    Verify Moq 默认情况下检查参数的引用相等性,因此它仅在您在测试和实现中提供相同实例(除非您已覆盖 Equals)时通过。

    在您的情况下,expectedA.Value 只返回在测试中创建的 new A { P1 = 1 },当然,这与在 DoSomethingWith 中创建的实例不同。

    您需要使用 Moq 的 It.Is 构造来正确测试它,而无需覆盖 Equals(事实上,您根本不需要 Autofixture):

    barMock.Verify(m => m.Something(It.Is<A>(arg => arg.P1 == a.P1)));
    

    但如果您有多个属性,例如 P1、P2、P3... AutoFixture 会很有用:

    barMock.Verify(m => m.Something(It.Is<A>(arg => expectedA.Equals(a))));
    

    因为您不需要为所有属性手动写出相等检查。

    【讨论】:

    • +1 特别是最后一个解决方案是使用 Likeness 的正确方法。 FWIW 有一个为 Likeness 提供新功能的工作项,使其能够动态发出覆盖 Equals 的代理,这将大大简化上述语法:autofixture.codeplex.com/workitem/4230
    • 漂亮,已应用 +1!
    【解决方案2】:

    如果您升级到 AutoFixture 2.9.1(或更高版本),您可以在 Likeness 实例上调用 CreateProxy 方法,该方法将为目标类型发出动态代理。

    生成的动态代理使用 Likeness 覆盖 Equals,这简化了语法(很多)。

    这是原始的测试方法,修改为使用 Likeness 代理:

    [Test]
    public void TestSample()
    {
        var foo = new Foo();
        var barMock = new Mock<IBar>();
        var expected = new A().AsSource().OfLikeness<A>().CreateProxy();
        expected.P1 = 1;
    
        foo.DoSomethingWith(barMock.Object);
    
        Assert.True(expected.Equals(foo.Data));     // passes
        barMock.Verify(m => m.Something(expected)); // passes
    }
    

    请注意,它还使测试断言比接受 Any 实例更具体。

    您可以找到有关此新功能here 的更多详细信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-18
      • 1970-01-01
      • 2011-05-08
      • 2011-06-24
      • 2012-11-09
      • 2018-07-16
      • 2012-04-12
      • 1970-01-01
      相关资源
      最近更新 更多