使用Verify确认Moq模拟类中的预期参数值

时间:2012-01-16 17:16:07

标签: nunit moq autofixture

我正在尝试验证使用期望的对象参数调用mock中的方法。我正在使用Moq,nUnit,并认为AutoFixture的相似性应该完成工作。 以下是我正在尝试做的简化版本。

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

覆盖A类中的等于比较属性值并将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
        }
    }
}

2 个答案:

答案 0 :(得分:64)

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

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

你需要使用Moq的It.Is构造来正确地测试它,而不会覆盖Equals(事实上,你根本不需要自动混合):

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 :(得分:5)

如果升级到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找到更多详细信息。