2014-04-18 14 views
11

Ho la seguente classe, che utilizza l'iniezione del costruttore:Come chiamare costruttore con argomenti di interfaccia quando beffardo una classe concreta con Moq

public class Service : IService 
{ 
    public Service(IRepository repository, IProvider provider) { ... } 
} 

Per la maggior parte dei metodi di questa classe, ho semplicemente creare Moq schernisce per IRepository e IProvider e costruire lo Service. Tuttavia, esiste un metodo nella classe che chiama diversi altri metodi nella stessa classe. Per testare questo metodo, invece di testare tutti questi metodi insieme, voglio testare che il metodo chiami quei metodi correttamente ed elabori correttamente i loro valori di ritorno.

Il modo migliore per farlo è prendere in giro Service. Ho preso in giro lezioni concrete con Moq prima senza problemi. Ho persino preso in giro lezioni concrete che richiedono argomenti di costruzione con Moq senza problemi. Tuttavia, questa è la prima volta che ho bisogno di passare gli argomenti in modo fittizio con nel costruttore per un oggetto deriso. Naturalmente, ho provato a farlo in questo modo:

var repository = new Mock<IRepository>(); 
var provider = new Mock<IProvider>(); 

var service = new Mock<Service>(repository.Object, provider.Object); 

Tuttavia, ciò non funziona. Invece, ottengo il seguente errore:

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: My.Namespace.Service. 
Could not find a constructor that would match given arguments: 
    Castle.Proxies.IRepository 
    Castle.Proxies.IProvider 

Questo funziona bene se il costruttore Service s' prende argomenti semplici come int s e string s, ma non se ci vuole interfacce che sto beffardi. Come fai a fare questo?

+1

Quale versione di Moq e castello stai usando? Perché il tuo codice di esempio funziona correttamente usando Moq 4.2.1312.1622 e Castle.Core 3.2.2 ... – nemesv

risposta

4

Ho avuto un problema molto simile quando il mio equivalente di Service aveva un costruttore interno, quindi non era visibile a Moq.

ho aggiunto

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 

al mio file AssemblyInfo.cs per il progetto di attuazione. Non sono sicuro se sia pertinente, ma volevo aggiungere un suggerimento sulla possibilità che ti aiuti o qualcun altro.

1

Deve essere un problema di versione precedente, tutto è ok con l'ultima versione. Nick, per favore controlla!

P.s .: Ho iniziato la taglia con misstake (avevo una firma sbagliata nel mio costruttore).

3

Perché stai prendendo in giro il servizio che stai testando? Se si desidera testare l'implementazione della classe Service (che si tratti di chiamate a oggetti di simulazione o meno), tutto ciò di cui si ha bisogno sono le mock per le due interfacce, non la classe di test.

Invece di:

var repository = new Mock<IRepository>(); 
var provider = new Mock<IProvider>(); 

var service = new Mock<Service>(repository.Object, provider.Object); 

non dovrebbe essere questo, invece?

var repository = new Mock<IRepository>(); 
var provider = new Mock<IProvider>(); 

var service = new Service(repository.Object, provider.Object); 

mi rendo conto che è possibile deridere oggetti concreti in alcuni quadri, ma che cosa è il vostro scopo? L'idea alla base del derisione è rimuovere l'implementazione effettiva in modo che non influenzi il test. Ma nella tua domanda, hai affermato che desideri sapere che determinate classi vengono chiamate correttamente, e poi desideri convalidare i risultati di tali azioni. Questo è senza dubbio un test per l'implementazione, e per questo motivo sto attraversando un periodo difficile nel vedere gli obiettivi di deridere l'oggetto concreto.

Problemi correlati