Насколько мне известно, AutoFixture автоматически рассматривает интерфейсы и абстрактные типы как макеты. Я думаю, что было бы неплохо включить в этот список и типы делегатов.
Прежде всего, не могли бы вы пояснить, с какой макетной средой вы работаете? У нас есть несколько интеграций (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.Fake1[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, безусловно, поддерживает фейки для делегатов:
@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 });
Самый полезный комментарий
Выпущено в версии 4.2.0! Включить:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });