Eu tenho um teste de unidade, que se parece com isso:
[Test]
public void Should_create_person()
{
Assert.DoesNotThrow(() => new Person(Guid.NewGuid(), new DateTime(1972, 01, 01));
}
Estou afirmando que um objeto Pessoa é criado aqui, ou seja, que a validação não falha. Por exemplo, se o Guid for nulo ou a data de nascimento for anterior a 01/01/1900, a validação falhará e uma exceção será lançada (significando que o teste falhará).
O construtor fica assim:
public Person(Id id, DateTime dateOfBirth) :
base(id)
{
if (dateOfBirth == null)
throw new ArgumentNullException("Date of Birth");
elseif (dateOfBith < new DateTime(1900,01,01)
throw new ArgumentException("Date of Birth");
DateOfBirth = dateOfBirth;
}
É uma boa ideia para um teste?
Nota : Estou seguindo uma abordagem classicista para testar a unidade do modelo de domínio, se isso tiver alguma influência.
c#
unit-testing
constructors
w0051977
fonte
fonte
Should_create_person
? O que deve criar uma pessoa? Dê a ele um nome significativo, comoCreating_person_with_valid_data_succeeds
.Respostas:
Esse é um teste válido (embora exagerado) e às vezes faço isso para testar a lógica do construtor, no entanto, como Laiv mencionou nos comentários, você deve se perguntar por quê.
Se o seu construtor estiver assim:
Há muito sentido em testar se lança? Se os parâmetros foram atribuídos corretamente, eu entendo, mas seu teste é um exagero.
No entanto, se o seu teste fizer algo assim:
Em seguida, seu teste se torna mais relevante (quando você está lançando exceções em algum lugar do código).
Uma coisa que eu diria, geralmente é uma prática ruim ter muita lógica em seu construtor. A validação básica (como as verificações nulas / padrão que estou fazendo acima) está ok. Mas se você está se conectando a bancos de dados e carregando dados de alguém, é aí que o código começa a cheirar muito ...
Por esse motivo, se vale a pena testar seu construtor (porque há muita lógica em andamento), talvez algo esteja errado.
Você certamente terá outros testes cobrindo essa classe em camadas de lógica de negócios, construtores e atribuições de variáveis certamente obterão cobertura completa desses testes. Portanto, talvez não faça sentido adicionar testes específicos especificamente para o construtor. No entanto, nada é preto e branco e eu não teria nada contra esses testes se estivesse analisando o código - mas questionaria se eles agregam muito valor acima e além dos testes em outras partes da sua solução.
No seu exemplo:
Você não está apenas validando, mas também está chamando um construtor de base. Para mim, isso fornece mais motivos para esses testes, pois eles agora têm a lógica de construtor / validação dividida em duas classes, o que diminui a visibilidade e aumenta o risco de alterações inesperadas.
TLDR
Há algum valor para esses testes, no entanto, a lógica de validação / atribuição provavelmente será coberta por outros testes em sua solução. Se há muita lógica nesses construtores que requer testes significativos, isso sugere para mim que há um cheiro desagradável de código à espreita.
fonte
PersonBirthdate
) que executa a validação da data de nascimento. Da mesma forma, aGuid
verificação pode ser implementada naId
classe. Isso significa que você realmente não precisa mais ter essa lógica de validação noPerson
construtor, pois não é possível construir uma com dados inválidos - excetonull
refs. Claro, você tem que escrever testes para as outras duas classes :)Já é uma boa resposta aqui, mas acho que vale a pena mencionar uma coisa adicional.
Ao fazer TDD "pelo livro", é preciso escrever um teste primeiro que chame o construtor, mesmo antes de o construtor ser implementado. Esse teste pode realmente parecer com o que você apresentou, mesmo se houvesse uma lógica de validação zero na implementação do construtor.
Observe também que, para TDD, deve-se escrever outro teste primeiro, como
antes de adicionar a verificação para
DateTime(1900,01,01)
o construtor.No contexto TDD, o teste mostrado faz todo sentido.
fonte