Обобщенная упаковка Func с анонимными значениями, эквивалентная AutoFixture 'With'

В тесте на основе AutoFixture я пытаюсь как можно точнее выразить следующее:

Когда я передаю <input> в параметр x этого метода, анонимно заполняя остальные параметры, результат...

Взяв пример фабричного метода: -

class X
{
    public static X Create( Guid a, Guid b, Guid c, String x, String y);

Я пытаюсь выразить в виде краткой серии тестов:

  1. Если я передам null для x, он должен выдать
  2. Если я передам null для y, он должен выбросить

Чтобы выразить, я могу сказать:

var fixture = Fixture();
var sut = default( Func<Guid, Guid, Guid,string,X>);
sut = fixture.Get( ( Guid anonA, Guid anonB, Guid anonC, string anonY ) => 
    x =>
        X.Create( anonA, anonB, anonC, x, anonY ) );

Assert.Throws<ArgumentNullException>( () => sut( null));

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

var fixture = Fixture();
var sut = default( Func<Guid, Guid, Guid,string,X> );
sut = fixture.Get( ( Guid anonA, Guid anonB, Guid anonC, string anonX ) => 
    y =>
        X.Create( anonA, anonB, anonC, anonX, y ) );
Assert.Throws<ArgumentNullException>( () => sut( null));

Для свойств в AutoFixture есть With. Есть ли эквивалент аргументов метода (и/или ctor)?

PS 0. Я не возражаю, если для этого случая необходимо попасть в «магические» строки, т. Е. Иметь бит x равным "x".

PS 1. Другой слон в комнате - это то, что я бьюсь головой о 4-кратные перегрузки Get в AutoFixture - или это потому, что у меня старая версия в этой среде?

PS 2. Также открыты для лучших предложений о том, как это смоделировать - до тех пор, пока они касаются того факта, что я хочу, чтобы это был вызов метода, а не свойства или поля (и я хотел бы, чтобы он работал в стиле AutoFixture). ).


person Ruben Bartelink    schedule 12.07.2012    source источник


Ответы (1)


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

Однако, если вам это нужно только для проверки работы Null Guards, вы можете использовать для этого AutoFixture.Idioms.

Вот пример.

var fixture = new Fixture();
var assertion = new GuardClauseAssertion(fixture);
var method = typeof(GuardedMethodHost).GetMethod("ConsumeStringAndInt32AndGuid");
assertion.Verify(method);

Если вы посмотрите на исходный код Ploeh.AutoFixture.IdiomsUnitTest.Scenario, вы Я найду другие примеры, но я признаю, что это одна из наиболее плохо документированных областей AutoFixture...

Другое дело, что методы с небольшим количеством параметров (или вообще без них) лучше, чем методы с большим количеством параметров, так что вы рассматривали введение объекта параметра?

person Mark Seemann    schedule 12.07.2012
comment
+1 Спасибо. Идиома, которую вы предлагаете, в значительной степени прибивает то, что мне нужно. Ранее я потратил некоторое время на изучение материала Idioms - как и AF, все очевидно, как только вы поднялись на начальном этапе изучения мухи слона, поэтому, хотя у меня было смутное представление о чем-то подобном, я не соединил точки, кроме как знать, что я нужно привлечь внимание @ploeh к этому вопросу. У вас есть точка зрения на актуальность Introduce Parameter Object, и, безусловно, есть другие случаи, когда ограничение вызвало проблему, которую вы хотите. Однако нынешний я бы поспорил за где-то 6-8 как разделительную черту больше 4 - person Ruben Bartelink; 12.07.2012
comment
то есть наличие перегрузок до 16 def будет плохим сигналом. Другая проблема заключается в том, что это круговой аргумент - я бы вернулся к исходной точке с необходимостью TDD в защитных предложениях в моем классе/структуре PO. - person Ruben Bartelink; 12.07.2012
comment
‹strike›По размышлению, я думаю, если бы я сделал сборку с явным ICustomization в цепочке, которая перехватывает создание образца для параметра верхнего уровня с именем x, возвращая заданное значение/результат функции. Тогда все, что мне нужно, это зажать нос, пока C# заставляет меня писать от руки .FromFactory<Guid, Guid, Guid, String, String)>( X.Create). ... так есть ли что-то, о чем я должен знать, что играет в этом пространстве? . Дох, это все ортогонально; Register...FromFactory - это то, как вы вводите фабричные методы, а идиома - это то, как вы тренируете охрану - комбинирование не требуется. - person Ruben Bartelink; 12.07.2012
comment
Это оставляет меня с желанием, чтобы максимальное число параметров перегруженного типа для FromFactory (и, возможно, некоторых других связанных методов) было доведено до 8, поскольку я хочу иметь возможность зарегистрировать фабричные методы, которые являются пограничными (до того, как они получат Introduce Parameter Objected в чистота). Имеет ли это смысл как ‹strike›issue/strike›pull request, или вы считаете, что ядро ​​должно оставаться самоуверенным на уровне 4 и заставлять людей поддерживать больше перегрузок с параметрами в качестве методов расширения в других местах. А пока спасибо за плюшевого медвежонка еще раз во время этого комментария. - person Ruben Bartelink; 12.07.2012
comment
Есть несколько причин, по которым FromFactory ограничен 4 входными параметрами. Первоначальная причина заключалась в том, что AutoFixture по-прежнему компилируется в .NET 3.5, поэтому Func с 4 параметрами является самым большим предопределенным делегатом. Хотя я мог бы создать пользовательских делегатов, я на самом деле считаю это очень подходящим ограничением. Как пишет дядя Боб в «Чистом коде», один параметр — это хорошо, а ноль — еще лучше. С этой точки зрения 4 уже слишком много, поэтому я не вижу смысла поддерживать что-то большее. - person Mark Seemann; 13.07.2012
comment
Тем не менее, если вам это нужно, вы всегда можете создать собственный ISpecimenBuilder, который действует как адаптер для более крупного Func, а затем использовать перегрузку FromFactory(ISpecimenBuilder), так что у вас все еще есть выход. - person Mark Seemann; 13.07.2012
comment
Обе части вашего аргумента по отдельности достаточно сильны, поэтому здесь нет аргументов. Поиграю с упомянутой вами перегрузкой, спасибо. - person Ruben Bartelink; 13.07.2012