Como faço para criar um construtor em C # para um objeto que tem propriedades que são tipos Referenc?

StackOverflow https://stackoverflow.com/questions/1402975

Pergunta

Eu comecei a construir um construtor para que eu possa facilmente criar dados de teste para testes de unidade Eu estou escrevendo.

A estrutura básica do construtor é:

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);
    }
}

O uso desse padrão torna-se então:

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

Eu estou confortável com isso ... mas onde eu tenho perguntas é quando MyClass tem uma propriedade que não é trivial .... Estou um pouco incerto sobre como proceder para construí-la com um valor padrão.

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);
    }
}

A minha suposição é que eu iria criar um construtor para MySecondClass e usar isso para criar a implementação padrão.

Alguém pode confirmar que a minha suposição é correta e é a melhor prática?

Eu estou atualmente no processo de testar a minha suposição, mas eu pensei que eu iria documentar essa idéia em StackOverflow uma vez que os únicos exemplos do padrão de construtor que eu poderia encontrar usando o Google apenas propriedades já construídas que são tipos de valor e não tipos de referência.

Foi útil?

Solução

Tal como acontece com a maioria das coisas -. Isso depende

Se você quiser semântica de referência no campo mySecondClass (isto é: você quer salvar uma referência a outra classe), então é exatamente como o seu inteiro. Ter o padrão ser nulo poderia ser perfeitamente aceitável.

No entanto, se você quiser garantir sempre um valor, você vai precisar para construir ou simplesmente construir um novo objeto para sua segunda classe.

Além disso, se você quiser clonagem em vez de cópias de referência, que você precisa para construir um novo objeto e atribuí-lo ao de referência.

Dito isto, em muitos casos, os construtores tradicionais são mais apropriados do que tentar fazer uma interface de estilo construção fluente. É realmente fácil de "estragar" uma interface fluente para a construção como esta, desde que você está contando com o usuário mais do que com um construtor tradicional.

Como exemplo, em seu código, o que acontece se o usuário nunca chama construir? Ainda está retornando algo (uma vez que cada um dos métodos retorna um objeto), mas é válido? Eu não seria certo como um consumidor de sua classe. construtores tradicionais com sobrecargas, por outro lado, mostra-me exatamente o que é válido eo que não é válido, e é tempo de compilação aplicadas.

Outras dicas

Assim que eu tiver um objeto complexo onde eu quero um manequim para usar em testes de unidade, eu vou geralmente recorrem a uma plataforma de simulacros / falsificação / isolamento. Em C #, a minha preferência é Moq, mas existem vários por aí, como Rhino Mocks, Typemock e assim por diante.

O benefício não é que eles normalmente têm a capacidade de stub todas as propriedades que existem no tipo original com valores padrão e objetos vazios, sem você ter que fazer outra coisa senão uma única instrução de linha para criar o objeto falso. Ao mesmo tempo, você pode facilmente configurar o objeto para retornar os valores que deseja para aqueles das propriedades que importa para o seu teste. Além disso, a maioria dessas estruturas de apoio fingindo de forma recursiva, de modo que os objetos complexos dentro do seu tipo também vai ser falsificado, e assim por diante.

Existem razões pelas quais não pode querer usar uma estrutura separada, caso em que eu acho que a sugestão de Reed Copsey seria a maneira manual para fazê-lo.

Se não há quaisquer razões para evitar a adição de uma plataforma de simulacros (que só seria uma dependência a seus projetos de teste, supondo que você dividir você testar), eu gostaria vivamente recomendo para tipos complexos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top