Модульное тестирование с помощью выражений? - PullRequest
0 голосов
/ 10 сентября 2009

Я выполняю модульное тестирование некоторого кода, который взаимодействует с хранилищем, для которого требуется выражение (Expression<Func<Entity, bool>>), чтобы отфильтровать результаты, например:

int orderId = 10;

_respository.GetFiltered(order => order.Id == orderId);

У меня проблема с модульным тестированием, в частности, с настройкой ожиданий соответствия выражения. В модульном тесте я хочу сделать это:

_mockRespository.Setup(r => r.GetFiltered(order => order.Id == 10)).Returns(new Order[0]).AtMostOnce();

Я нашел одно решение, которое предлагало бы делать .ToString() для каждого выражения и сравнивать его, однако, когда вы ссылаетесь на переменную, такую ​​как orderId, выражение совершенно другое!

Что люди делают, чтобы проверить это?

Спасибо

David

1 Ответ

0 голосов
/ 18 августа 2011

Я бы сказал, что отчасти это то, что вы на самом деле хотите проверить с помощью модульного теста, что сводится к вашей философии модульного тестирования.

Что мы делаем, так это то, что мы не обязательно проверяем, что параметр выражения linq to entity, переданный из типа A (в тесте), использует конкретное дерево выражений при вызове GetFoo () для сотрудника хранилища (не тестируется). Для модульного теста мы довольны проверкой того, что метод GetFoo () вообще вызывает правильную подпись.

В вашем случае похоже, что вы используете Moq (?), И в этом случае это может выглядеть примерно так (остерегайтесь синтаксического беспорядка)

_mockRespository.Setup(r => r.GetFiltered(It.IsAny<Expression<Func<Entity, bool>>>())).Returns(new Order[0]).AtMostOnce();

Для нас это имеет смысл, потому что а) проверка сравнения дерева выражений параметров метода имитации является действительно трудной задачей и б) даже если бы мы могли проверить этот параметр, то, как B на самом деле будет интерпретировать различные комбинации значений параметров, может измениться (как в семантике контракта A-> B), и в этом случае тест станет хрупким.

Мы используем автоматизированные тесты истории для тестирования взаимодействия между производством A и производством B. Мы думаем, что это лучший способ протестировать эти сценарии, поскольку они, как правило, представляют собой что-то вроде «фильтровать все A в хранилище в соответствии с выражением X и дать мне все объекты, которые соответствуют '. Для нас это имеет смысл в качестве интеграционных тестов (обычно достаточно одного или двух счастливых случаев).

Если вам этого недостаточно, я бы прочитал а) о том, как создавать пользовательские сопоставления Moq, хотя не могу с уверенностью сказать, что существует простое решение (оно вполне может быть) или б) настройка ожидание обратного вызова, так что вы можете захватить параметр и проверить его после теста. Примерно так:

    Expression<Func<Entity, bool>> actualExpression = null;
    _mockRespository.Setup(r => r.GetFiltered(It.IsAny<Expression<Func<Entity, bool>>>())).Returns(new Order[0]).AtMostOnce().Callback((Expression<Func<Entity, bool>> expr => { actualExpression = expr});

    // exercise production code

    Assert.IsTrue(actualExpression ...... someithing clever here);

Примечание. Весь приведенный выше код был написан в редакторе переполнения стека. Не привлекайте меня к ответственности, если он не компилируется, документы Moq охватывают это

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