2015-06-30 4 views
6

È possibile verificare se è stato chiamato un metodo utilizzando Moq and dependency injection. Tuttavia, è possibile testare se un metodo in una classe chiama un altro all'interno della stessa classe?Test se il metodo in ClassA è stato chiamato da un altro metodo in Classe A

Ad esempio, voglio verificare che se registro una certa eccezione, viene registrato anche un messaggio informativo.

Il metodo è:

public void Error(string message, Exception exception, long logId = 0) 
{ 
    var int32 = (int)logId; 
    Info("Id was converted to an int so that it would fit in the log: " + logId, int32); 
    Error(message, exception, int32); 
} 

Questo è stato il mio tentativo di unità di testarlo. Il test fallisce, esiste un modo per farlo?

void logging_an_error_with_a_long_id_also_logs_info() 
{ 
    var mock = new Mock<ILogger>(); 
    var testedClass = new Logger(); 
    var counter = 0; 

    testedClass.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue); 

    mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>())); 
} 

Poiché i Info e Error metodi sono nella stessa classe (ClassA), non ritengo posso passare ClasseA come una dipendenza in ClassA. Quindi non ha bisogno di essere testato?

+0

Dai un'occhiata [qui] (http://stackoverflow.com/questions/1417048/how-to-verify-another-method-in-the-class-was-called-using-moq). – dee

risposta

7

Il meglio che riuscirai a fare è rendere Infovirtual. Ciò ti consentirà di creare un Mock<Logger>, di impostare CallBase = true e di verificare che sia stato chiamato Info.

var mock = new Mock<Logger> 
{ 
    CallBase = true 
}; 

mock.Object.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue); 

mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>())); 

In questo modo, si sta ancora chiamando l'effettiva attuazione del Error, ma hai utilizzato Moq per verificare il metodo Info è stato chiamato.

+0

+1 funziona quando Mock viene utilizzato perché è necessaria la classe reale. Non funziona per l'interfaccia Mock . – dee

5

Sembra che tu stia cercando di testare la cosa sbagliata. Non è molto importante che il metodo Info della classe sia chiamato dal metodo Error, l'importante è che si verifichi il comportamento del metodo Info. Come succede è un dettaglio di implementazione della classe.

Se ho avuto una lezione di matematica con due funzioni:

public int Mult(int x, int y) { 
    return x*y; 
} 

public int Sqr(int x) { 
    return Mult(x,y); 
} 

non vorrei provare che chiamare Sqr chiamato fuori alla funzione Mult, ho iniziato ad esaminare Sqr(4)==16. Non importa se quel calcolo ha luogo nel metodo Sqr o in un altro metodo della classe.

Mentre @solution di Andrew è probabilmente quello che stai cercando, prendere in giro la classe che stai testando tende a condurre test strettamente accoppiati e fragili.

Se non è pratico testare la chiamata osservando i suoi effetti collaterali, potrebbe essere un segnale che l'implementazione potrebbe utilizzare un po 'di refactoring.

+0

È più facile dire che probabilmente c'è un modo migliore rispetto a fornire un modo migliore – Hoppe

+0

@Hoppe Anche se è vero, per fornire un modo migliore spesso è necessario più contesto di quello fornito (ad esempio, non ho idea di quale sia il contenuto del tuo I metodi Error o Info sono). A volte il meglio che si può fare è indicare una direzione alternativa, che in alcuni aprirà una porta che permetterà loro di guardare il loro problema in un modo diverso. – forsvarir