Tengo una prueba de unidad, que se ve así:
[Test]
public void Should_create_person()
{
Assert.DoesNotThrow(() => new Person(Guid.NewGuid(), new DateTime(1972, 01, 01));
}
Estoy afirmando que un objeto Persona se crea aquí, es decir, que la validación no falla. Por ejemplo, si el Guid es nulo o la fecha de nacimiento es anterior al 01/01/1900, entonces la validación fallará y se lanzará una excepción (lo que significa que la prueba falla).
El constructor se ve así:
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;
}
¿Es esta una buena idea para una prueba?
Nota : Estoy siguiendo un enfoque clasicista para la Unidad de Prueba del Modelo de Dominio si eso tiene alguna relación.
c#
unit-testing
constructors
w0051977
fuente
fuente
Should_create_person
? ¿Qué debería crear una persona? Dale un nombre significativo, comoCreating_person_with_valid_data_succeeds
.Respuestas:
Esta es una prueba válida (aunque bastante entusiasta) y a veces lo hago para probar la lógica del constructor, sin embargo, como mencionó Laiv en los comentarios, debe preguntarse por qué.
Si su constructor se ve así:
¿Tiene mucho sentido probar si arroja? Si los parámetros están asignados correctamente, puedo entenderlo, pero su prueba es bastante exagerada.
Sin embargo, si su prueba hace algo como esto:
Luego, su prueba se vuelve más relevante (ya que en realidad está lanzando excepciones en algún lugar del código).
Una cosa que diría es que, en general, es una mala práctica tener mucha lógica en su constructor. La validación básica (como las comprobaciones nulas / predeterminadas que estoy haciendo arriba) están bien. Pero si se está conectando a bases de datos y cargando datos de alguien, entonces es donde el código comienza a oler realmente ...
Debido a esto, si vale la pena probar su constructor (porque hay mucha lógica en marcha), entonces tal vez algo más esté mal.
Es casi seguro que tendrá otras pruebas que cubren esta clase en capas de lógica de negocios, los constructores y las asignaciones variables seguramente obtendrán una cobertura completa de estas pruebas. Por lo tanto, quizás no tenga sentido agregar pruebas específicas específicamente para el constructor. Sin embargo, nada es en blanco y negro y no tendría nada en contra de estas pruebas si estuviera revisando el código, pero me preguntaría si agregan mucho valor por encima y más allá de las pruebas en otra parte de su solución.
En tu ejemplo:
No solo está validando, sino que también está llamando a un constructor base. Para mí, esto proporciona más razones para tener estas pruebas, ya que ahora tienen la lógica del constructor / validación dividida en dos clases, lo que disminuye la visibilidad y aumenta el riesgo de cambios inesperados.
TLDR
Estas pruebas tienen cierto valor, sin embargo, es probable que la lógica de validación / asignación esté cubierta por otras pruebas en su solución. Si hay mucha lógica en estos constructores que requiere pruebas significativas, entonces me sugiere que hay un desagradable olor a código acechando allí.
fuente
PersonBirthdate
) que realiza la validación de la fecha de nacimiento. Del mismo modo, laGuid
verificación podría implementarse en laId
clase. Esto significa que ya no es necesario tener esa lógica de validación en elPerson
constructor, ya que no es posible construir uno con datos no válidos, a excepción de lasnull
referencias. Por supuesto, tienes que escribir pruebas para las otras dos clases :)Ya hay una buena respuesta aquí, pero creo que vale la pena mencionar una cosa adicional.
Cuando se hace TDD "por libro", primero se necesita escribir una prueba que llame al constructor, incluso antes de que el constructor se implemente. Esa prueba en realidad podría parecerse a la que presentó, incluso si no hubiera lógica de validación dentro de la implementación del constructor.
Tenga en cuenta también que para TDD, primero se debe escribir otra prueba como
antes de agregar la verificación para
DateTime(1900,01,01)
al constructor.En el contexto TDD, la prueba mostrada tiene mucho sentido.
fuente