2012-07-24 3 views
6

Voglio prendere in giro Microsoft.Office.Interop.Excel.Range (e le altre interfacce Microsoft.Office.Interop.Excel) sull'unità testare la mia applicazione. Sto usando Moq 4.0.10827 con .NET 4 in C#.Come simulare Microsoft.Office.Interop.Excel.Range con Moq?

Nel mio test di unità, tento di configurare il comportamento del finto come segue:

 var range = new Mock<Microsoft.Office.Interop.Excel.Range>(); 
     range.Setup(r => r.get_Value(1)).Returns("Something"); 

     var classBeingTested = new MyClass(range.Object); 

Nel codice essendo unità testato, sto usando la Range come segue:

public MyClass(Range range) 
    { 
     var value = range[1].ToString(); 
    } 

Quando il test viene eseguito, si produce la seguente eccezione:

 Error: Missing method 'instance object [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get__Default(object,object)' from class 'Castle.Proxies.RangeProxy'. 

Come posso implementare questa mockin g con successo? Mi rendo conto che isolare la funzionalità di interoperabilità di Excel con un modello come https://stackoverflow.com/a/9486226/1548950 è una potenziale soluzione; tuttavia, sarei più felice con la possibilità di creare mock dalle interfacce Microsoft.Office.Interop.Excel.

EDIT: Maggiori dettagli su questo tema

OK, questo è strano. Ho creato un progetto per testare il suggerimento di jimmy_keen. Funziona. Tuttavia, quando uso la stessa suggestione per testare il progetto che avevo problemi con, getta la seguente eccezione:

Error: Missing method 'instance object [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get__Default(object,object)' from class 'Castle.Proxies.RangeProxy'. 

Dal suggerimento di jimmy_keen ha funzionato bene su altri progetti, ho iniziato a sospettare che ci sia qualcosa di sbagliato con il progetto sto testando il codice con. Così, ho creato un soluzione test che illustra il problema in dettaglio: http://www7.zippyshare.com/v/70834394/file.html

La radice del problema sembra essere che il progetto contiene un'altra classe (che non viene unità testato) con sostanzialmente il seguente codice:

Non capisco perché questo causa il problema, perché non sto usando UnTestedClass nel test di unità a tutti. Mi sto perdendo qualcosa nel modo in cui dovrei usare Moq, o mi sono imbattuto in un bug?

+0

+1 Questo è strano, immagino che abbia qualcosa a che fare con gli oggetti COM. Non appena faccio riferimento all'interop di Excel, non posso più fare riferimento alla mia libreria Moq ... Weird ... – jsmith

+0

Dopo aver lavorato su questo, mi sto ora spostando verso l'isolamento della funzionalità Microsoft.Office.Interop.Excel con il mio classi e interfacce personalizzate invece di prendere in giro Microsoft.Office.Interop.Excel. * direttamente. Mentre la risposta a questa domanda risolve i problemi immediati, in fin dei conti Microsoft.Office.Interop.Excel. * Ha appena iniziato a richiedere troppo lavoro di installazione per renderlo utile. –

risposta

5

Il codice accede indicizzatore, e questo è ciò che è necessario prendere in giro:

var range = new Mock<Microsoft.Office.Interop.Excel.Range>(); 
range.Setup(r => r[1, It.IsAny<object>()]).Returns("something"); 

Nota che Range indicizzatore ha effettivamente due parametri - da qui il vincolo It.IsAny<object>() in chiamata.

+0

Grazie, ho provato questo e funziona in alcuni casi. Tuttavia, il test unitario su cui sto lavorando si rifiuta ancora ostinatamente di lavorare. Si prega di consultare la soluzione di test che ho caricato su http://www7.zippyshare.com/v/70834394/file.html –

+2

@LauriHarpf: questo è interessante. Apparentemente è un "problema" con il codice generato dal compilatore.L'interfaccia di tipo 'Range' generata dal compilatore nel tuo * Progetto * ha proprietà extra (' Column', ovvero). Non ho idea di come questo potrebbe essere problematico per Castle ... ma è COM. Ad esempio, se verifichi i tuoi assemblaggi con ILSpy, vedrai cosa intendo. Il codice generato dal compilatore è diverso (anche se le classi sono le stesse) e questo deve essere il problema. Si noti che se si esegue lo stub 'range.Setup (r => r.Column) .Returns (0);' anche questo test passerà. –

+1

Eccellente, grazie! Anche la punta di ILSpy era d'oro; nel mio vero progetto, vedo altre proprietà extra che appaiono in aggiunta a Column. Presenti sono "Colonna", "Colonne", "Riga", "Righe" e "Valore". Questo comportamento probabilmente renderà tutti i test unitari che scrivo in modo abbastanza fragile, perché in qualsiasi momento potrebbero apparire nuove proprietà e rompere qualcosa. In ogni caso, usando i tuoi suggerimenti e prendendo in giro con cura tutte le proprietà extra funziona così, contrassegnando come risposta. Grazie Signore! –