Как дождаться вызова, который принимает определенное выражение linq в качестве аргумента

У меня есть вызов, который я хочу проверить. Этот вызов относится к методу, который принимает выражение Linq в качестве аргумента. Это выражение проверяет идентификатор объекта на соответствие идентификатору локальной переменной, в которой объявлено выражение. Как я могу сделать поддельный простой вызов, который срабатывает только тогда, когда выражения Linq равны (с заменой локальной переменной) или если это невозможно, срабатывает, когда локальная переменная, используемая в выражении linq, равна определенному значению.

Мой текущий код выглядит так

   A.CallTo(() => SomeMethod.FindBy(item=> item.ItemId == 3)).MustHaveHappened(Repeated.Exactly.Once);

Как вызов и this в тестируемом коде.

SomeMethod.FindBy(item=> item.ItemId == id)

где id — локальная переменная. Это не работает, так как идентификатор не подставляется при вызове, и я получаю такую ​​​​ошибку.

SomeInterface`1[[someItem, someItemFolder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].FindBy(item=> (item.ItemId == 3))
  Expected to find it exactly once but found it #0 times among the calls:
    1: SomeInterface`1[UKHO.WeeklyRecipes.EFModels.EFModels.EfTag].FindBy(predicate: tag => (tag.TagId == value(UKHO.WeeklyRecipes.BusinessLayer.PreferenceQueries+<>c__DisplayClass2_0).id))

person milo.farrell    schedule 14.07.2017    source источник


Ответы (1)


Вы видите такое поведение, потому что FakeItEasy не может определить, совпадают ли два выражения. Когда вы предоставляете объект в качестве ограничения аргумента, FakeItEasy пытается точно соответствовать значению аргумента. В данном случае это означает вызов метода Equals Expression. Чтобы процитировать документацию:

При проверке равенства аргументов FakeItEasy использует object.Equals. Если проверяемый тип не предоставляет адекватного метода Equals, возможно, вам придется использовать метод That.Matches, описанный в Пользовательское соответствие. Будьте особенно осторожны с типами, чьи методы Equals выполняют равенство ссылок, а не равенство значений. В этом случае объекты должны быть одним и тем же объектом для сопоставления, и это иногда приводит к неожиданным результатам. Если вы сомневаетесь, проверьте поведение типа Equals вручную.

По сути, это означает, что если вы создадите две переменные, одна из которых содержит выражение item => item.ItemId == 3, а другая item.ItemId == id, и сравните их, используя Equals, вы увидите результат false, как и FakeItEasy.

Один из подходов состоит в том, чтобы зафиксировать выражение, а затем опросить его, чтобы увидеть, действует ли оно так, как вам нравится (то есть, но принимает 3 и отклоняет не 3). Это неудобно, но сравнивать предикаты сложно. Подробнее об этом я рассказываю в ответе на Как проверить совпадение с FakeItEasy при вызове предиката?.

person Blair Conrad    schedule 14.07.2017