2011-10-21 15 views
7

Io attualmente eseguire test che assomigliano a quanto segue:Come utilizzare moq per testare codice che chiama aiutanti protetti

// 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()); 

    } 

} 

È possibile che questo guarda bene per le cose semplici, ma la classe stub ottiene esponenzialmente più grande e più complessa rapidamente . Mi piacerebbe sostituire la classe stub usando Moq. Tuttavia questo non verrà compilato perché per qualche motivo non posso impostare un valore di ritorno su un metodo protetto.

[TestMethod] 

public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

{ 

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

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

} 

Qualcuno sa come andrei a fare questo? Posso farlo con moq?

+5

Qualcosa non sembra proprio qui ... non prendi in giro il tuo SUT, prendi in giro le sue dipendenze. –

+0

Sì, in realtà Yojin prende in giro il SUT per sostituire una parte del SUT che dovrebbe essere tenuta separata, non in un metodo di supporto protetto. – Matthias

risposta

23

Guardando il moq source code I'd indovinare è necessario chiamare esplicitamente la versione generica di installazione. La versione non generica sembra essere usata per i metodi void. Quindi prova

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

Oltre a questo, consiglierei di ripensare il design della tua classe. Se HelperMethod() sta facendo un sacco di cose, varrebbe la sua classe che viene iniettata come dipendenza in ClassUnderTest. Testare un oggetto mock, invece di usare un oggetto mock per testare qualcosa di "reale", non è ciò per cui sono fatti i framework di simulazione (non in primo luogo, almeno).

4

I metodi protetti non sono un ottimo modo per isolare le dipendenze, ma a volte si verificano, in particolare quando si adatta il codice legacy per la testabilità. Un'opzione che evita la sintassi Moq scomoda basata su stringhe è rendere il metodo 'protected internal' (o solo 'internal' se non si intende sovrascriverlo nel normale utilizzo da altri assembly). Quindi si usa InternalsVisibleTo sull'assembly per esporre il metodo. Questo è un po 'un trucco, ma usare un metodo protetto per questo scopo è già un po' un trucco. Per certi versi preferisco l'approccio "interno", in quanto chiarisce che si tratta di un metodo backdoor che non dovresti usare (tranne che per i test), al contrario di un metodo protetto che potresti prevedere di sovrascrivere in modalità normale utilizzo.

Problemi correlati