2011-10-21 11 views
7

Yo ahora pruebas que se parecen a lo siguiente:Cómo utilizar moq para probar código que llama ayudantes protegidos

// In Blah.cs 
public class ClassUnderTest 

{ 

    public bool MethodUnderTest() 

    { 

     // Do a bunch of stuff... 

     return HelperMethod(); 

    } 



    protected virtual bool HelperMethod() 

    { 

     bool success = false; 

     // Proprietary Hardware Access. 

     // Database Calls. 

     // File System Modifications. 

     return success; 

    } 

} 


// In TestBlah.cs 

public class TestStub : ClassUnderTest 

{ 

    public bool HelperMethodReturnValue; 



    protected override bool HelperMethod() 

    { 

     return HelperMethodReturnValue; 

    } 

} 



[TestClass] 

public class TestingClass 

{ 

    [TestMethod] 

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsTrue() 

    { 

     var stub = new TestStub(); 

     stub.HelperMethodReturnValue = true; 

     Assert.IsTrue(stub.MethodUnderTest()); 

    } 



    [TestMethod] 

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

    { 

     var stub = new TestStub(); 

     stub.HelperMethodReturnValue = false; 

     Assert.IsFalse(stub.MethodUnderTest()); 

    } 

} 

Lo anterior se ve muy bien para cosas simples, sin embargo, la clase stub obtiene exponencialmente más grande y más compleja rápidamente . Me gustaría reemplazar la clase de stub con Moq. Sin embargo, esto no se compilará porque, por alguna razón, no puedo establecer un valor de retorno en un método protegido.

[TestMethod] 

public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

{ 

    var mockClass = new Mock<ClassUnderTest>(); 
    mockClass.Protected().Setup("HelperMethod").Returns(false); 

    Assert.IsFalse(mockClass.Object.MethodUnderTest()); 

} 

¿Alguien sabe cómo voy a hacer esto? ¿Puedo hacer esto con moq?

+5

Algo no parece correcto aquí ... no se burla de su SUT, se burla de sus dependencias. –

+0

Sí, en realidad Yojin se burla del SUT para reemplazar una parte del SUT que debe mantenerse separada, no en un método de ayuda protegido. – Matthias

Respuesta

23

Mirando el moq source code que había suposición necesita llamar explícitamente la versión genérica de la instalación. La versión no genérica parece ser usada para métodos de vacío. Así que trate de

mockClass.Protected().Setup<bool>("HelperMethod").Returns(false); 

Junto a esto, me gustaría recomendar re-pensar el diseño de su clase. Si HelperMethod() está haciendo un montón de cosas, valdría la pena su propia clase que se inyecta como una dependencia en ClassUnderTest. Probar un objeto falso, en lugar de usar un objeto simulado para probar algo "real", no es para lo que están hechos los marcos burlones (al menos no en primer lugar).

4

Los métodos protegidos no son una excelente manera de aislar las dependencias, pero a veces surgen, especialmente cuando se adapta el código heredado para la comprobación. Una opción que evita la incómoda sintaxis de Moq basada en cadenas es hacer que el método sea 'interno protegido' (o simplemente 'interno' si no tiene la intención de anularlo en el uso normal de otros ensamblajes). A continuación, utiliza InternalsVisibleTo en el ensamblaje para exponer el método. Esto es un truco, pero usar un método protegido para este fin ya es un poco complicado. De alguna manera, prefiero el enfoque "interno", ya que deja en claro que se trata de un método de puerta trasera que no se debe usar (excepto para las pruebas), a diferencia de un método protegido que se puede esperar anular en condiciones normales. uso.

Cuestiones relacionadas