Использование FakeItEasy с параметром выражения Linq

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

В системе используется Entity Framework, а один из классов управления данными обрабатывает пользователей, и я пытаюсь выяснить, как протестировать только базовую функцию GetUserByUserNumber. Я могу использовать фальшивое IPersistenceManager<User> при создании экземпляра класса UserDataManager, а затем вызвать метод GetUserByUserNumber, но утверждение для проверки того, что userPersistenceManager.ReadCustom было вызвано, всегда терпит неудачу.

Я попытался вызвать метод Delete для поддельного userPersistenceManager, и утверждение для этого работает нормально. Я думаю, что это как-то связано с выражением Linq, которое метод ReadCustom принимает в качестве своего первого параметра. Я просто не знаю, как это должно быть обработано. Любая помощь в этом будет оценена по достоинству!

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

public User GetUserByUserNumber(string userNumber, bool loadRelatedRecords = false)
{
    if (string.IsNullOrWhiteSpace(userNumber))
    {
        throw MyAppExceptions.CreateMyAppFatalException(Constants.ExceptionKeys.Unexpected, new ArgumentNullException("userNumber"));
    }
    Logger.Write(string.Format("Executing GetUserByUserNumber with UserNumber {0}.", userNumber), LogCategory.General, TraceEventType.Verbose);
    return _UserPersistenceManager.ReadCustom(mem => mem.UserNumber == userNumber, EntityConstants.EntityNames.UserDetail);
}

Это метод IPersistenceManager, который я хочу убедиться, что он вызывается:

TEntity ReadCustom(Expression<Func<TEntity, bool>> predicate, string includeEntityName);

Это мой модульный тест:

[TestMethod]
public void GetUserByUserNumber_Calls_ReadCustom()
{
    // Arrange
    var userPersistenceManager = A.Fake<IPersistenceManager<User>>();
    var dataManager = new UserDataManager(userPersistenceManager);

    // Act
    dataManager.GetUserByUserNumber("123456", false);

    // Assert
    A.CallTo(() => userPersistenceManager.ReadCustom(u => u.UserNumber == "123456", EntityConstants.EntityNames.UserDetail)).MustHaveHappened();
}

person ADent    schedule 29.11.2013    source источник


Ответы (2)


Я думаю, что ответ Тима Лонга по сути правильный, хотя я считаю, что это не недостаток насмешливых фреймворков - все сводится к тому, насколько легко (в целом, а не только при насмешке) определить, являются ли две вещи «одинаковыми».

Проблема в том, что если не указано иное, FakeItEasy использует .Equals для сравнения аргументов. Expression плохо сочетаются с .Equals, поэтому вы получите несоответствие. Один из вариантов — изучить Expression средства проверки на равенство. В StackOverflow уже есть ряд вопросов по этому поводу, например Как проверить, совпадают ли два Expression‹Func‹T, bool››. Если вы можете найти хороший способ определить равенство выражений, я думаю, вы могли бы предоставить этот метод для сопоставления аргументов FakeItEasy
(например, с A<Expression<Func<TEntity, bool>>.That.Matches(…)).

Кроме того, вы можете пойти по пути мистера Лонга и зафиксировать аргумент, а затем допросить его позже. Я предложил аналогичный подход совсем недавно, отвечая на Как подделать действие‹› с FakeItEasy.

В вашем случае вы можете зафиксировать предикат, а затем проверить его правильность, посмотрев, как он реагирует на различные входные объекты - похожи ли они на UserNumber "123456".

person Blair Conrad    schedule 30.11.2013

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

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

person Tim Long    schedule 30.11.2013