Использование деревьев выражений в качестве ограничения аргумента - PullRequest
2 голосов
/ 27 сентября 2011

Могу ли я использовать дерево выражений в качестве ограничения аргумента в утверждении FakeIteasy CallTo?

Учитывая метод в интерфейсе со следующей подписью:

interface IRepository<TEntity>
{
    TEntity Single(Expression<Func<TEntity, bool>> predicate);

Вызывается в коде, какИтак:

Flight flight = repository.Single(f => f.ID == id);

Я имею в виду модульный тест, выполняющий что-то вроде этого:

Expression<Func<Flight, bool>> myExpression = flight => flight.ID == 1;

A.CallTo(() => repository.Single(
                  A<Expression<Func<Flight, bool>>>.That.Matches(myExpression)))
                  .Returns(new Flight());

Однако это выдает предупреждение: Попробуйте явно указать аргументы типа .

В настоящее время мне приходится использовать свойство Ignored, которое не является идеальным.

Ответы [ 3 ]

2 голосов
/ 11 октября 2011

Спасибо, Патрик,

Изучение выражения было именно тем, что мне нужно было сделать, то есть разобрать выражение ( f => f.ID == id ) и выполнить правую часть== чтобы получить значение времени выполнения.

В коде это выглядит так:

A.CallTo(() => flightRepository.Single(A<Expression<Func<Flight, bool>>>.That
                .Matches(exp => Expression.Lambda<Func<int>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == 1)))
                .Returns(new Flight());

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

Еще раз спасибо, Майкл Макдауэлл

2 голосов
/ 29 сентября 2011

Метод "Matches" принимает лямбду, но вы пытаетесь передать ему выражение. Что вы пытаетесь сказать с помощью «Матчей»? Вы совпадаете на равенство? В этом случае вы просто напишите:

A.CallTo (() => хранилище. Single (myExpression)). Возвращает (new Flight ());

Если вы хотите ограничить выражение чем-то другим, вам нужно передать предикат типа: Func<Expression<Func<Flight, bool>>, bool> методу "Matches".

0 голосов
/ 22 ноября 2011

У меня была такая же проблема при попытке утвердить выражение в качестве аргумента, но я использовал Moq. Решение должно работать для вас, хотя и ...

Я отдаю большую часть оценки этому ответу на аналогичный вопрос: Moq Expect On IRepository Passing Выражение

В основном это говорит о том, что вы можете сделать ToString () для выражений и сравнить их. Это отчасти хакерство, но у него есть только один недостаток; имена переменных в лямбда-выражении должны совпадать.

Вот пример ...

    [Test]
    public void TestWhichComparesExpressions()
    {
        // setup
        _mockRepository.Setup(x => x.GetByFilter(MatchQuery())).Returns(new List<Record>());

        // execute
        var records = _service.GetRecordsByFilter();

        // assert
        Assert.IsNotNull(records);
        Assert.AreEqual(0, records.Count());
    }

    private static Expression<Func<DomainRecord, bool>> MatchQuery()
    {
        return MatchExpression(ServiceClass.QueryForTheRecords); // constant
    }

    // /223463/moq-expect-na-irepository-prohozhdenie-vyrazheniya#223473
    private static Expression<Func<DomainRecord, bool>> MatchExpression(Expression<Func<DomainRecord, bool>> expression)
    {
        return It.Is<Expression<Func<DomainRecord, bool>>>(e => e.ToString() == expression.ToString());
    }

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

...