2012-05-25 18 views
16

Estoy tratando de aprender a hacer pruebas unitarias con C# y Moq, y he construido una pequeña situación de prueba. Dado este código:Unidad probando un método con Moq

public interface IUser 
{ 

    int CalculateAge(); 
    DateTime DateOfBirth { get; set; } 
    string Name { get; set; } 
} 

public class User : IUser 
{ 
    public DateTime DateOfBirth { get; set; } 
    string Name { get; set; } 

    public int CalculateAge() 
    { 
     return DateTime.Now.Year - DateOfBirth.Year; 
    } 
} 

Quiero probar el método CalculateAge(). Para ello, pensé que debería tratar de darle un valor por defecto a la propiedad DateOfBirth al hacer esto en mi método de prueba:

var userMock = new Mock<IUser>(); 
userMock.SetupProperty(u => u.DateOfBirth, new DateTime(1990, 3, 25)); //Is this supposed to give a default value for the property DateOfBirth ? 
Assert.AreEqual(22, userMock.Object.CalculateAge()); 

Pero cuando se trata de la afirmación, el valor de CalculateAge() es igual a 0, aunque DateOfBirth iguales new DateTime(1990, 3, 25).

Sé que esto puede parecer un ejemplo tonto, pero lo que sea ... Pensé que podría usar la burla para dar valores a los métodos/propiedades aún no desarrollados en mis objetos, por lo que la prueba de un método no lo haría Depender de otro componente de mi clase, o incluso configurar un contexto predeterminado para mi objeto (de ahí el nombre del usuario aquí ...) ¿Me estoy acercando a este problema de la manera incorrecta?

Gracias.

+1

* Realmente * buen artículo que se alinea en paralelo con su pregunta: http://kakimotonline.com/2011/01/02/unit-testing-net-application-with-moq-framework/ – atconway

Respuesta

23

Sí, te estás equivocando, pero no te preocupes, explicaré por qué. Primer indicio sería

puede eliminar por completo su clase User y todo va a ser el mismo .

cuando se están haciendo:

var userMock = new Mock<IUser>(); 

Usted acaba de crear un \ objeto de burla falsa de esa interfaz, que no tiene nada que ver con la clase inicial User, por lo que no tiene ninguna aplicación de CalculateAge método, excepto el falso que simplemente devuelve 0. Es por eso que obtienes 0 en tu declaración de afirmación.

Por lo tanto, usted decía:

pensaron que podría utilizar burla para dar valores a los que aún no es desarrollada método/propiedades en mis objetos, por lo que la prueba de un método no depende de otro componente de mi clase

usted podría, digamos que usted tendrá un poco de los consumidores de su IUser, digamos como el siguiente:

class ConsumerOfIUser 
{ 
    public int Consume(IUser user) 
    { 
     return user.CalculateAge() + 10; 
    } 
} 

en ese caso burla de IUser tendrá sentido total, ya que desea probar cómo se comporta cuando sus ConsumerOfIUser IUser.CalculateAge() devuelve 10. Se podría hacer lo siguiente:

var userMock = new Mock<IUser>(); 
userMock.Setup(u => u.CalculateAge()).Returns(10); 

var consumer = new ConsumerOfIUser(); 
var result = consumer.Consume(userMock); 

Assert.AreEqual(result, 20); //should be true 
+0

Así que no hay absolutamente ninguna razón usar burla mientras prueba solo una clase? Solo, quiero decir que no hay interacción con otras clases. Por ejemplo, digamos que tengo un método que descarga muchas cosas, y eso demora 10 minutos en ejecutarse. Y que CalculateAge() usa un valor devuelto por este método ... ¿Sería útil simular este resultado? (Digamos que DateOfBirth fue ese método de descarga de 10 minutos, en lugar de solo una propiedad de auto) – Pacane

+4

@Pacane, eso es correcto. Probar una clase sin dependencias externas (en su forma más pura) no debería requerir un simulacro o un apéndice. – lbergnehr

+2

El método para descargar cosas debe escribirse en otra clase, que puede ser burlada para la prueba. – Ben

2

Depende de lo que su tratando Probar. En este caso, ha burlado el objeto Usuario, por lo que no tiene sentido probar nada dentro de esta clase ya que lo está reemplazando con un objeto simulado. Si desea probar el objeto Usuario, entonces no debe simularlo.

Los simuladores se utilizan para reemplazar objetos dependientes que no desea probar. Por ejemplo, si tenía un objeto Name en lugar de una cadena (por ejemplo, contiene el nombre, el apellido, el título, etc.) pero no deseaba probar el objeto Nombre, solo el objeto Usuario, crearía una simulación del objeto Nombre que se utilizará al construir el objeto Usuario.

Cuestiones relacionadas