2009-10-29 10 views
31

considerar esta clase:Moq - Cómo verificar que un valor de la propiedad se establece a través de la incubadora

public class Content 
{  
    public virtual bool IsCheckedOut {get; private set;} 
    public virtual void CheckOut() 
    { 
     IsCheckedOut = true; 
    } 

    public virtual void CheckIn() 
    { 
     //Do Nothing for now as demonstrating false positive test. 
    } 
} 

El método El registro es intencionalmente vacía. Ahora tengo algunos métodos de prueba para verificar el estado de llamar a cada método.

[TestMethod] 
public void CheckOutSetsCheckedOutStatusToTrue() 
{ 
    Content c = new Content();  
    c.CheckOut(); 
    Assert.AreEqual(true, c.IsCheckedOut); //Test works as expected 
} 

[TestMethod] 
public void CheckInSetsCheckedOutStatusToFalse() 
{ 
    Content c = new Content(); 
    c.CheckIn(); 
    Assert.AreEqual(false, c.IsCheckedOut); //Test does not work as expected 
} 

La segunda prueba pasa por los motivos equivocados. Entonces, ¿cómo puedo usar burla (moq) para verificar que CheckIn establezca la propiedad IsCheckedOut?

Gracias.

EDITAR

Para aclarar: Tengo un método llamado Check In() cuyo trabajo es para establecer el estado IsCheckedOut a falso.

Verás en mi código de prueba anterior que la prueba arrojará falso aunque no establezca el valor de la propiedad en falso; Esto es esperado, nada está mal aquí.

Creo que mi pregunta es específicamente ¿Cómo puedo verificar que el método CheckIn() haya establecido la propiedad IsCheckedOut en false? Esto es lo que yo llamaría verificación de comportamiento.

Creo que algunos de los comentarios sugirieron hacer algo que equivale a la verificación del estado? Si por lo que no creo que haya ningún valor en burlarse de esta parte del todo cuando simplemente puede utilizar:

Content c = new Content();  
c.CheckIn();  
Assert.AreEqual(false, c.IsCheckedOut); //State verification 

Por supuesto puedo estar equivocado, así que por favor, ayúdame a aclarar estos conceptos :)

+0

Realmente depende del propósito de la propiedad IsChecked out: si es un comportamiento del objeto que después de que algo se haya registrado y desprotegido es falso, entonces lo que tienes arriba está bien. Si la propiedad es una ventana hacia su clase para verificar un comportamiento mayor, eso sería lo que yo llamaría verificación de estado. Entonces ... depende de la intención realmente. – FinnNk

+0

Esto pareció resolver el problema: http://stackoverflow.com/questions/2853313/moq-how-to-correctly-mock-set-only-properties –

+0

no responde a la pregunta directamente, pero necesario para comprobar que una propiedad se estableció explícitamente como verdadera: 'mock.SetupProperty (foo => foo.SomeProperty);/* ejecutar acciones de prueba * /; mock.VerifySet (foo => foo.SomeProperty = It.IsAny (), "SomeProperty debería haberse configurado"); Assert.True (mock.Object.SomeProperty, "SomeProperty debería haberse establecido en verdadero"); ' –

Respuesta

33

Lo siguiente debería funcionar Configurar el objeto de burla como:

var mock=new Mock<IContent>(); 
mock.SetupSet(content => content.IsCheckedOut=It.IsAny<bool>()).Verifiable(); 

Y después de que el código de prueba:

mock.VerifySet(content => content.IsCheckedOut=It.IsAny<bool>()); 

no he probado todos modos, así que por favor dime si funciona para usted.

EDIT. De hecho, esto no funcionará ya que el setter para IsCheckedOut es falso.

De todos modos, ahora veo que nunca se establece el valor de IsCheckedOut en el tiempo de construcción de la clase. Sería una buena idea añadir lo siguiente a la clase Content:

public Content() 
{ 
    IsCheckedOut=false; 
} 
+0

Para aclarar.No quiero probar al colocador en la propiedad IsCheckedOut, en su lugar quiero probar que el método CheckIn() ha establecido IsCheckedOut = false; Además, la propiedad IsCheckedOut es privada, por lo que no creo que la configuración funcione. ¿Es posible con lo que quiero hacer? ¿Alguna idea más? –

+0

IsCheckedOut está en su interfaz, por lo que no puede ser privado? – FinnNk

+0

FinnNk: solo el getter está en la interfaz, el setter es privado. – Konamiman

2

¿Puedo sugerir que usted podría estar pensando en esto de la manera equivocada - por lo general debe estar fijándose algo, la realización de una acción y luego verificando el comportamiento (resultado). En este caso, realmente importa que el colocador no lo configure como falso, lo que debería importar es que sea falso después de que se haya ejercido un escenario determinado. Si tomas las pruebas por separado, esto puede parecer un poco extraño, pero para cualquier cosa tus pruebas existirán en conjuntos.

La situación sería diferente si estuviera probando la interacción entre dos clases, entonces estaría bien establecer una expectativa sobre el establecimiento de propiedades, ya que la acción de configuración es la interacción que está probando.

No estoy familiarizado con Moq porque uso Rhino.Mocks, pero supongo que habrá algo parecido a Mock.VerifySet (content => content.IsCheckedOut = It.IsEqual (true)) ;

+0

Por favor, vea mi publicación editada :) –

4

¿por qué no simplemente configura el contenido que se va a revisar para empezar? Recuerde, usted solo está probando el comportamiento de la función CheckIn.

[TestMethod] 
public void CheckInSetsCheckedOutStatusToFalse() 
{ 
    // arrange - create a checked out item 
    Content c = new Content(); 
    c.CheckOut(); 

    // act - check it in 
    c.CheckIn(); 

    // assert - IsCheckedOut should be set back to false 
    Assert.AreEqual(false, c.IsCheckedOut); 
} 
+2

Acepto que el uso de un marco simulado no es necesario en este caso. Este método sugerido es mejor ya que prueba la interfaz pública en lugar de los detalles internos (es decir, cómo se establece la propiedad). – Cellfish

0

estoy de acuerdo con usted: burla no tiene ningún valor en este escenario, ya que se pretende poner a prueba las interacciones entre su clase (en prueba) y el resto del mundo, no para probar el mecanismo interno de tu clase.

creo que esta prueba

Content c = new Content();  
c.CheckIn();  
Assert.AreEqual(false, c.IsCheckedOut); //State verification 

que escribe tiene sentido y no es un falso positivo! Debe asegurarse de que el estado sea así después del CheckIn, independientemente de por qué es así; si en el futuro establecerá el estado en el constructor (u otros métodos), esta prueba lo salvará y se verá obligado a implementar el método CheckIn.

En algunos casos similares a su deseo de establecer el estado inicial para asegurarse de que no olvide implementar el método CheckIn; en este caso utilizo 2 métodos (el primero es muy feo):

  1. Llamo a c.CheckOut() antes de c.CheckIn(); esto es muy feo, porque se prueba 2 métodos en vez de uno ... pero admito que escribí algo similar pocas veces :-)
  2. hago la incubadora privada protegida, y escribo una clase de prueba que hereda de la clase bajo prueba; de esta manera puedo configurar la propiedad en true antes de llamar a c.CheckIn() para asegurarme de que el método está haciendo su trabajo.

aquí está el código:

public class Content2 
{ 
    public virtual bool IsCheckedOut { get; protected set; } 
    public virtual void CheckOut() 
    { 
     IsCheckedOut = true; 
    } 

    public virtual void CheckIn() 
    { 
     //Do Nothing for now as demonstrating false positive test. 
    } 
} 

    [TestClass] 
public class Content2Test : Content2 
{ 
    [TestMethod] 
    public void CheckOutSetsCheckedOutStatusToTrue() 
    { 
     this.CheckOut(); 
     Assert.AreEqual(true, this.IsCheckedOut); //Test works as expected 
    } 

    [TestMethod] 
    public void CheckInSetsCheckedOutStatusToFalse() 
    { 
     this.IsCheckedOut = true; 
     this.CheckIn(); 
     Assert.AreEqual(false, this.IsCheckedOut); //Test does not work as expected 
    } 
} 

Esperanza para ayudar.

Cuestiones relacionadas