2009-09-10 1 views
0

Я начал строить строитель, чтобы я мог легко создавать тестовые данные для модульных тестов, которые я пишу.Как создать построитель в C# для объекта, который имеет свойства, которые являются ссылочными типами?

Основная структура строитель:

public class MyClassBuilder 
{ 
    public int id = 0; //setting the default value here 

    //allows MyClass to be built with a specific id 
    public MyClassBuilder WithId(int id) 
    { 
     this.id = id; 
     return this; 
    } 

    public MyClass Build() 
    { 
     return new MyClass(id); 
    } 
} 

Использование этой модели становится:

MyClass mc = new MyClassBuilder().WithId(5).Build(); 

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

public class MyClassBuilder 
{ 
    public int id = 0; //setting the default value here 

    //do I construct the default value using a MySecondClassBuilder? 
    public MySecondClass mySecondClass; 

    //allows MyClass to be built with a specific id 
    public MyClassBuilder WithId(int id) 
    { 
     this.id = id; 
     return this; 
    } 

    public MyClassBuilder WithMySecondClass(MySecondClass mySecondClass) 
    { 
     this.mySecondClass = mySecondClass; 
    } 

    public MyClass Build() 
    { 
     return new MyClass(id); 
    } 
} 

Мое предположение, что я хотел бы создать конструктор для MySecondClass и использовать, чтобы создать реализацию по умолчанию.

Может ли кто-нибудь подтвердить, что мое предположение верно и является наилучшей практикой?

В настоящее время я тестирую свое предположение, но я думал, что буду документировать эту идею в StackOverflow с единственными примерами шаблона компоновщика, который мог бы найти с использованием только когда-либо построенных свойств Google, которые являются типами значений и а не ссылочные типы.

ответ

1

Как и большинство вещей - это зависит.

Если вам нужна эталонная семантика в поле mySecondClass (то есть: вы хотите сохранить ссылку на другой класс), то это точно так же, как ваше целое число. По умолчанию значение null может быть вполне приемлемым.

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

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

Это, во многих случаях, традиционные конструкторы более подходят, чем попытка свободного интерфейса стиля сборки. Очень легко «испортить» свободный интерфейс для построения, как это, поскольку вы полагаетесь на пользователя больше, чем на традиционный конструктор.

В качестве примера, в вашем коде, что произойдет, если пользователь никогда не вызывает Build? Он все еще возвращает что-то (поскольку каждый из методов возвращает объект), но действительно ли он? Я не был бы уверен, как потребитель вашего класса. Традиционные конструкторы с перегрузками, с другой стороны, показывают мне, что действительно и что недействительно, и выполняются во время компиляции.

+0

Все, что я хочу использовать для этих сборщиков, это создание объектов для использования в моих модульных тестах, чтобы я мог знать, что они полностью сконструированы и не будут генерировать ненужные ссылочные исключения при использовании частями кода I Не тестировать. Это немного разъясняет? – mezoid

+0

Не совсем. Это одна из основных причин использования традиционных конструкторов с перегрузками - обычный стандартный конструктор ВСЕГДА оставит объект в работоспособном состоянии (при условии, что класс хорошо разработан), поскольку такие строители могут вызвать всевозможные проблемы. Если ваши классы таковы, ваши модульные тесты могут просто построить их, используя стандартные конструкторы. Как это проще, чем стандартный конструктор (плюс дополнительный инициализатор объекта)? http://msdn.microsoft.com/en-us/library/bb384062.aspx –

+0

Ну, класс, который я пытаюсь построить, представляет собой класс, который автоматически генерируется для использования NHibernate для представления одной из таблиц в базе данных , Он имеет более 30 параметров для конструктора, который делает конструкцию объектов для использования в модульных тестах очень утомительной ... тем более, что мне приходится вручную создавать многие параметры, которые мне действительно не нужны. – mezoid

0

Как только у меня есть сложный объект, где я хочу использовать манекен в модульных тестах, я обычно перехожу к фальшивке/фальсификации/изоляции. В C# я предпочитаю Moq, но есть несколько таких, как Rhino Mocks, Typemock и так далее.

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

Есть причины, по которым вы не можете использовать отдельную структуру, и в этом случае я думаю, что предложение Рида Копси было бы ручным способом сделать это.

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

Смежные вопросы