2011-01-22 12 views
40

Ho il seguente metodo:Utilizzando moq per deridere solo alcuni metodi

public CustomObect MyMethod() 
{ 
    var lUser = GetCurrentUser(); 
    if (lUser.HaveAccess) 
    { 
     //One behavior 
    } 
    else 
    { 
     //Other behavior 
    } 

    //return CustomObject 
} 

voglio deridere IMyInterface.GetCurrentUser, in modo che durante la chiamata MyMethod ho potuto ottenere a uno dei percorsi di codice a controllare. Come farlo con Moq?

sto facendo la cosa seguente:

var moq = new Mock<IMyInterface>();    
moq.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser); 

//act 
var lResult = moq.Object.MyMethod(); 

Ma per qualche motivo è sempre lResultnull e quando sto cercando di entrare in MyMethod in di debug ho sempre saltare per l'istruzione successiva.

+0

Dove è stato inizializzato l'uso di 'lUnauthorizedUser'? Immagino che tu voglia qualcosa come 'moq.Setup (x => x.GetCurrentUser()). Restituisce (nuovo utente() {HaveAccess = falso});' –

+0

Tyler, sicuro che lo sto impostando nel codice sopra , semplicemente non l'ha incollato per mantenere il codice breve. –

risposta

83

Questo è chiamato un falso parziale e il modo in cui so di farlo in moq richiede il mocking della classe piuttosto che l'interfaccia e quindi l'impostazione della proprietà "Callbase" sul tuo oggetto mocked su "true".

Ciò richiederà rendere tutti i metodi e le proprietà della classe che si sta testando virtuale. Supponendo che questo non è un problema, si può quindi scrivere un test come questo:

var mock = new Mock<YourTestClass>(); 
mock.CallBase = true; 
mock.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser); 
mockedTest.Object.MyMethod(); 
+0

Fantastico! Grazie mille, non pensavo fosse così semplice. –

+0

funziona come un fascino !!! –

11

Ampliando lee's answer,

Non è necessario per fare tutti i metodi e le proprietà sulla vostra classe virtuale, solo quelli che desideri deridere.

Inoltre, si dovrebbe notare che si dovrebbe prendere in giro l'implementazione concreta della classe.

var mock = new Mock<YourTestClass>(); // vs. var mock = new Mock<IYourTestInterface>();

Se la classe non ha un costruttore di default, sarà anche necessario specificare argomenti da passare dentro ad esso tramite:

var mock = new Mock<YourTestClass>(x, y, z); 
// or 
var mock = new Mock<YourTestClass>(MockBehavior.Default, x, y, z); 

Dove x, y, z sono il primo, secondo e terzo parametri per il costruttore, rispettivamente.

E, infine, se il metodo si sta cercando di prendere in giro è protetto è necessario includere Moq.Protected

using Moq.Protected; 

TReturnType returnValue = default(TReturnType); 

mock.Protected() 
    .Setup<TReturnType>("YourMockMethodName", It.IsAny<int>()) // methodname followed by arguments 
    .Returns(returnValue); 
+0

Vale la pena notare che è possibile utilizzare 'nameof (YourTestClass.YourMockMethodName)' invece di "YourMockMethodName". A causa di ciò, quando si effettua il refactoring, il test del nome del metodo continuerà a funzionare. – Shoter

4

ho avuto un caso simile. Ho trovato il seguente codice mi ha dato una maggiore flessibilità di utilizzare entrambi i metodi deriso e metodi attuali da qualche specifica implementazione di un'interfaccia:

var mock = new Mock<ITestClass>(); // Create Mock of interface 

// Create instance of ITestClass implementation you want to use 
var inst = new ActualTestClass(); 

// Setup to call method of an actual instance 
// if method returns void use mock.Setup(...).Callback(...) 
mock.Setup(m => m.SomeMethod(It.IsAny<int>()) 
    .Returns((int x) => inst.SomeMethod(x)); 

Ora è possibile utilizzare il metodo attuale, ma anche utilizzare le cose come Verifica per vedere quante volte è stato chiamato.

+0

Che Sir .... è un lavoro interessante in giro: D – ppumkin

Problemi correlati