С помощью Moq вы можете проверить вызов метода с анонимным типом? - PullRequest
13 голосов
/ 27 марта 2012

Я пытаюсь проверить вызов метода, используя Moq, но не могу понять синтаксис правильно.В настоящее время я использую это как подтверждение:

repository.Verify(x => x.ExecuteNonQuery("fav_AddFavorites", new
{
    fid = 123,
    inputStr = "000456"
}), Times.Once());

Код компилируется, но тест завершается неудачно с ошибкой:

Expected invocation on the mock once, but was 0 times: 
x => x.ExecuteNonQuery("fav_AddFavorites", new <>f__AnonymousType0<Int32, String>(123, "000456"))
No setups configured.

Performed invocations:
IRepository.ExecuteNonQuery("fav_AddFavorites", { fid = 123, inputStr = 000456 })

Как проверить вызов метода и сопоставитьПараметры метода для анонимного типа.

ОБНОВЛЕНИЕ

Чтобы ответить на вопросы:

Я пытаюсь убедиться, что метод был вызван и чтопараметры верны.

Подпись метода, который я пытаюсь проверить:

int ExecuteNonQuery(string query, object param = null);

Код установки просто:

repository = new Mock<IRepository>();

ОБНОВЛЕНИЕ 2

Похоже, что это проблема с Moq и как он обрабатывает анонимные типы в .Net.Код, написанный Полом Матовичем, работает нормально, однако, как только код и тест находятся в разных сборках, тест завершается неудачей.

Ответы [ 3 ]

10 голосов
/ 28 марта 2012

это проходит

        public class Class1
    {
        private Class2 _Class2;
        public Class1(Class2 class2)
        {
            _Class2 = class2;
        }

        public void DoSomething(string s)
        {
            _Class2.ExecuteNonQuery(s, new { fid = 123,  inputStr = "000456" });
        }
    }

    public class Class2
    {
        public virtual void ExecuteNonQuery(string s, object o)
        {
        }
    }

    /// <summary>
    ///A test for ExecuteNonQuery
    ///</summary>
    [TestMethod()]
    public void ExecuteNonQueryTest()
    {
        string testString = "Hello";
        var Class2Stub = new Mock<Class2>();
        Class1 target = new Class1(Class2Stub.Object);
        target.DoSomething(testString);
        Class2Stub.Verify(x => x.ExecuteNonQuery(testString, It.Is<object>(o => o.Equals(new { fid = 123, inputStr = "000456" }))), Times.Once());
    }

Обновление

Странно, он не работает в разных сборках. Кто-то может дать нам длинное определение того, почему object.equals из разных сборок ведут себя по-разному, но для разных сборок это будет работать, любая разница в значениях объекта будет возвращать другой хеш-код.

        Class2Stub.Verify(x => x.ExecuteNonQuery(testString, It.Is<object>(o => o.GetHashCode() == (new { fid = 123, inputStr = "000456" }).GetHashCode())), Times.Once());
6 голосов
/ 18 марта 2014

Один из вариантов - «проверить» его в обратном вызове.Очевидно, это необходимо сделать во время установки, например:

aMock.Setup(x => x.Method(It.IsAny<object>())).Callback<object>(
  (p1) =>
    {
      dynamic o = p1;
      Assert.That(o.Name, Is.EqualTo("Bilbo"));
    });
0 голосов
/ 26 октября 2018

Ни один из ответов не является хорошим, если ваша тестовая сборка отличается от сборки тестируемой системы (действительно часто). Вот мое решение, которое использует сериализацию Json, а затем сравнение строк.

Функция теста помощника:

using Newtonsoft.Json;

public static class VerifyHelper
{
    public static bool AreEqualObjects(object expected, object actual)
    {
        var expectedJson = JsonConvert.SerializeObject(expected);
        var actualJson = JsonConvert.SerializeObject(actual);

        return expectedJson == actualJson;
    }
}

Пример тестируемой системы:

public void DoWork(string input)
{
     var obj = new { Prop1 = input };
     dependency.SomeDependencyFunction(obj);
}

Пример модульного теста:

var expectedObject = new { Prop1 = "foo" };

sut.DoWork("foo");
dependency.Verify(x => x.SomeDependencyFunction(It.Is<object>(y => VerifyHelper.AreEqualObjects(expectedObject, y))), Times.Once());

Это решение действительно простое, и я думаю, что облегчает понимание модульного теста в отличие от других ответов в этой теме. Однако, поскольку он использует простое сравнение строк, анонимный объект теста должен быть настроен точно так же, как и анонимный объект тестируемой системы. Итак, допустим, вы хотели проверить только значение одного свойства, но тестируемая система устанавливает дополнительные свойства для анонимного объекта, вашему модульному тесту нужно будет установить все эти другие свойства (и в том же точном порядке) для вспомогательная функция для возврата true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...