Подтвердить что ты не робот

Использование Verify для подтверждения ожидаемых значений параметров в классе Moq mock

Я пытаюсь проверить, что метод внутри mock вызывается с ожидаемым параметром объекта. Я использую Moq, nUnit и думаю, что AutoFixture Likeness должен выполнить свою работу. Ниже приведен упрощенный вариант того, что я пытаюсь сделать.

Есть ли способ сделать это с помощью AutoFixture? Есть ли лучший способ проверить, что Something вызывается с соответствующим параметром?

Переопределение равных в классе A для сравнения значений свойств и изменения строки Verify на:

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

но я бы предпочел не переопределять Equals в каждом классе, таком как A в моем проекте.

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
        }
    }
}
4b9b3361

Ответ 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))));

Поскольку вам не нужно вручную выставлять проверки eqaulity для всех свойств.

Ответ 2

Если вы обновляетесь до AutoFixture 2.9.1 (или новее), вы можете вызвать метод CreateProxy в экземпляре Likeness, который выдает динамический прокси для целевого типа.

Сгенерированный динамический прокси переопределяет Equals, используя Likeness, который упрощает синтаксис (довольно много).

Вот оригинальный метод тестирования, модифицированный для использования прокси-сервера 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
}

Обратите внимание, что это также делает утверждение теста более конкретным, чем принятие любого экземпляра.

Подробнее об этой новой функции можно найти .