Autofixture: Относитесь к делегатам как к фейкам с FakeItEasy

Созданный на 16 февр. 2018  ·  15Комментарии  ·  Источник: AutoFixture/AutoFixture

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

enhancement good first issue

Самый полезный комментарий

Выпущено в версии 4.2.0! Включить:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });

Все 15 Комментарий

Прежде всего, не могли бы вы пояснить, с какой макетной средой вы работаете? У нас есть несколько интеграций (Moq, NSubsitute, FakeItEasy), поэтому непонятно. Насколько мне известно, делегаты уже поддерживаются интеграцией Moq (по крайней мере, это упоминается в # 742).

Также, насколько мне известно, AutoFixture имеет собственный механизм генерации делегатов. Есть ли у вас с этим проблемы?

@zvirja Я использую FakeItEasy. Поэтому я меняю название проблемы
Следующий код возвращает Fake после применения настройки:
var myFake= fixture.Create<ISomeInterface>();

Однако этого не происходит:
var myFake= fixture.Create<Func<int,int>>();

Приведенный выше код просто возвращает ненастоящий фиктивный делегат.

Более того, следующий сбой с ошибкой:

var myFake= fixture.Create<Fake<Func<int,int>>>();

AutoFixture.ObjectCreationExceptionWithPath
HResult = 0x80131500
Сообщение = AutoFixture не удалось создать экземпляр из System.IntPtr, потому что создание неожиданно завершилось ошибкой с исключением. Обратитесь к внутреннему исключению, чтобы выяснить основную причину сбоя.

Путь запроса:
FakeItEasy.Fake 1[System.Func 2 [System.Int32, System.Int32]]
IntPtr метод
System.IntPtr

Внутренние сообщения об исключениях:
AutoFixture.Kernel.IllegalRequestException: обнаружен запрос IntPtr. Это небезопасный ресурс, который приведет к сбою процесса при использовании, поэтому запрос будет отклонен. Обычным источником запросов IntPtr являются запросы для делегатов, таких как Funcили действие. В этом случае ожидаемый обходной путь - настроить (зарегистрировать или внедрить) проблемный тип, указав правильную стратегию создания.

Источник =
Трассировки стека:

Внутреннее исключение 1:
IllegalRequestException: обнаружен запрос IntPtr. Это небезопасный ресурс, который приведет к сбою процесса при использовании, поэтому запрос будет отклонен. Обычным источником запросов IntPtr являются запросы для делегатов, таких как Funcили действие. В этом случае ожидаемый обходной путь - настроить (зарегистрировать или внедрить) вызывающий нарушение тип, указав правильную стратегию создания.

@OnurGumus Я кратко исследовал эту проблему, и мне кажется, что FakeItEasy поддерживает насмешку над делегатами. Делегаты не упоминаются в их документации.

Также я протестировал следующий код, и он не прошел с исключением (что доказывает, что функция не поддерживается):
c# A.Fake<Func<int, int>>();

Поэтому не похоже, что AutoFixture может что-то с этим поделать.

Не могли бы вы подробнее описать желаемое поведение? Делегат очень легко имитировать, так как его можно указать с помощью примитивного лямбда-выражения, так зачем вам макеты?

@zvirja , FakeItEasy, безусловно, поддерживает фейки для делегатов:
image

@blairconrad Не могли бы вы найти несколько минут и пролить свет на это? Поддерживает ли FakeItEasy издевательство над делегатами? Если да, то каков синтаксис? Мой образец выше не помог мне, но может случиться так, что я что-то пропустил ...: confused:

Спасибо

@zvirja , рада. Как говорит @OnurGumus , FakeItEasy с радостью подделает делегатов (и я создал проблему, чтобы задокументировать это).
Однако AutoFakeItEasy никогда не беспокоился о подделке делегатов.

При подделке Fake<Func<int, int>> , например, FakeItEasyMethodQuery.SelectMethods не работает, потому что не учитывается случай Fake<T> где T является делегатом. Очень наивное изменение, приведенное ниже, исправляет это.

@@ -33,7 +33,7 @@ namespace Ploeh.AutoFixture.AutoFakeItEasy
             }

             var fakeType = type.GetFakedType();
-            if (fakeType.IsInterface)
+            if (fakeType.IsInterface || fakeType.IsSubclassOf(typeof(Delegate)))
             {
                 return new[] { new ConstructorMethod(type.GetDefaultConstructor()) };
             }

Затем я могу создать и использовать Fake<Func<int, int>> .

Что касается создания Func<int, int> , я быстро попробовал и обнаружил, что прибор использует DelegateGenerator для создания делегата (не FakeItEasy).
Между вами и мной меня всегда смущала архитектура AutoFixture и отношения между строителем и реле и еще много чего, но я могу продолжить исследование и увидеть, где находится разрыв.

Я вернулся. Я могу понять. FakeItEasyRelay добавляется к сборщикам остатков фикстуры, но DelegateGenerator сначала создает делегата.
Быстрый поиск не показал, как вставить конструктор FakeItEasy раньше в цепочку, но, возможно, я неправильно смотрю.

Независимо от того, как это обернется, я был бы рад отправить PR, чтобы разрешить издевательство над Fake<TDelegate> где TDelegate - тип делегата.

@blairconrad, как пользователь FakeItEasy, очень хочу вашего пиара :)

@blairconrad Спасибо за разъяснения и за расследование! Я только что проверил еще раз и обнаружил, что FakeItEasy действительно создает фейки для делегатов. Наверное, я что-то пропустил в предыдущем тесте 😖

Что касается создания Func, Я быстро попробовал и обнаружил, что прибор использует DelegateGenerator для создания делегата (не FakeItEasy).

Ага. У нас точно такая ResidueCollectors получит возможность вмешаться.

Предлагаю исправить эту проблему следующим образом:

  • Расширение запроса метода для поддержки запросов Fake<Delegate> ;
  • Добавьте новую настройку, которая добавит реле в коллекцию Customizations , чтобы запрос делегата обрабатывался (ретранслировался) _ до_ обработки ядром AutoFixture. Это означает, что эта функция не будет активирована по умолчанию, однако пользователи могут легко включить ее, используя предопределенную настройку.

@blairconrad Кроме того, не могли бы вы описать, в чем преимущество поддельного делегата по сравнению с делегатом, созданным AutoFixture? На данный момент мне приходит в голову только одно - вы можете настроить их, используя синтаксис конфигурации поддельной библиотеки.

Спасибо, @zvirja.

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

Я счастлив расширить запрос метода для поддержки Fake<Delegate> и добавлю дополнительную настройку, как вы говорите, но задаюсь вопросом: достаточно ли хорошо тот, который поддерживает Delegate ? Что происходит, когда следующая ошибка, о которой сообщается, хочет, чтобы IEnumerable или Task или IDictionary были подделаны FakeItEasy?

О, @zvirja запросила подтверждение синтаксиса подделки делегата. Теперь он был объединен с документацией FakeItEasy с помощью FakeItEasy / FakeItEasy # 1321, но для ясности:

`` С #
var fakeDelegate = A.Fake> ();

is the preferred syntax for clients, although "unnatural fakes" can be used:

```c#
var fakeDelegate = new Fake<Func<int, int>>();

В последнем случае класс FakeItEasyBuilder создаст объект Fake.

Интересный факт: фальшивые делегаты не поддерживались до версии 1.7.4257.42 (вероятно, коммит FakeItEasy / FakeItEasy @ edb4f61d0db0a84b68c7a9395f2661a58579d34a). Лично я без проблем могу сказать: «Вы не получите этого, если не используете хотя бы эту версию FakeItEasy». @zvirja или другие, считаете ли вы это проблемой? Мне придется проделать некоторые трюки с модульными тестами, чтобы убедиться, что мы не нарушаем существующие тесты AutoFakeItEasyUnitTest.
Если вы не хотите обновить минимальную версию FakeItEasy для этого исправления. Я бы, вероятно, не стал бы, тем более что запрос делегата в этих версиях в любом случае потерпел бы неудачу.

@blairconrad Большое спасибо за вашу работу над этим!

@zvirja или другие, считаете ли вы это проблемой?

Вовсе нет. Согласно SemVer, за которым мы здесь следуем, нам не разрешено изменять версию зависимости в той же основной версии. Поэтому я бы сказал, что правильным шагом было бы добавить такую ​​поддержку для версий FakeItEasy, которые поддерживают эту функцию. Позже мы, возможно, захотим отказаться от поддержки 1.x в v5 (для единообразия), но это произойдет только в будущем.

Преобразование этой проблемы в функцию, поскольку мы согласились продолжить ее (и FakeItEasy поддерживает делегатов).

Выпущено в версии 4.2.0! Включить:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });

Была ли эта страница полезной?
0 / 5 - 0 рейтинги