2012-07-24 31 views
6

Quiero burlarme de Microsoft.Office.Interop.Excel.Range (y las otras interfaces Microsoft.Office.Interop.Excel) para probar mi aplicación. Estoy usando Moq 4.0.10827 con .NET 4 en C#.Cómo simular Microsoft.Office.Interop.Excel.Range con Moq?

En mi prueba de unidad, lo intento de establecer el comportamiento de la maqueta de la siguiente manera:

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

     var classBeingTested = new MyClass(range.Object); 

En el código que se está probando la unidad, estoy usando el rango de la siguiente manera:

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

Cuando la prueba se ejecuta, se produce la siguiente excepción:

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

¿Cómo puedo poner en práctica esta Mockin g con éxito? Me doy cuenta de que aislar la funcionalidad de Excel Interop con un patrón como https://stackoverflow.com/a/9486226/1548950 es una solución potencial; sin embargo, estaría más feliz de poder crear burlas desde las interfaces Microsoft.Office.Interop.Excel.

EDIT: Más detalles sobre este tema

OK, esto es extraño. Creé un proyecto para probar la sugerencia de jimmy_keen. Funciona. Sin embargo, cuando se utiliza la misma sugerencia para probar el proyecto que tenía problemas con, que arroja la siguiente excepción:

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

Desde la sugerencia de jimmy_keen funcionó bien en otros proyectos, empecé a sospechar que hay algo mal con el proyecto con el que estoy probando el código Por lo tanto, he creado una solución de prueba que demuestra el problema en detalle: http://www7.zippyshare.com/v/70834394/file.html

La raíz del problema parece ser que el proyecto contiene otra clase (que no se está probando la unidad) con esencialmente el siguiente código:

using Microsoft.Office.Interop.Excel; 
namespace Project 
{ 
    public class UnTestedClass 
    { 
     public UnTestedClass(Worksheet sheet) 
     { 
      var foo = sheet.Range["Description"].Column; 
     } 
    } 
} 

No entiendo por qué esto causa el problema, porque no estoy usando UnTestedClass en la prueba de la unidad en absoluto. ¿Me estoy perdiendo algo de cómo debo usar Moq, o me he topado con un error?

+0

+1 Esto es extraño, supongo que tiene algo que ver con los objetos COM. Tan pronto como hago referencia a la interoperabilidad de Excel, ya no puedo hacer referencia a mi biblioteca Moq ... Extraño ... – jsmith

+0

Después de trabajar un poco en esto, ahora me estoy moviendo hacia el aislamiento de la funcionalidad Microsoft.Office.Interop.Excel con la mía clases e interfaces personalizadas en lugar de burlarse de Microsoft.Office.Interop.Excel. * directamente. Si bien la respuesta a esta pregunta resuelve los problemas inmediatos, burlarse de Microsoft.Office.Interop.Excel. * En última instancia, acaba de comenzar a requerir demasiado trabajo de configuración para que sea útil. –

Respuesta

5

Su código de acceso a controlador paso a paso, y eso es lo que hay que burlarse:

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

Tenga en cuenta que Range indexador en realidad tiene dos parámetros - de ahí el It.IsAny<object>() limitación de llamada.

+0

Gracias, probé esto y funciona en algunos casos. Sin embargo, la prueba de la unidad en la que estoy trabajando todavía obstinadamente se niega a funcionar. Consulte la solución de prueba que he cargado en http://www7.zippyshare.com/v/70834394/file.html –

+2

@LauriHarpf: esto es interesante. Aparentemente es un "problema" con el código generado por el compilador.La interfaz de tipo 'Range' generada por el compilador en su * Project * tiene una propiedad extra (' Column', concretamente). No tengo idea de cómo esto podría ser problemático para Castle ... pero es COM. Si revisa sus ensamblajes con ILSpy por ejemplo, verá lo que quiero decir. El código generado por el compilador difiere (incluso si las clases son las mismas) y este debe ser el problema. Tenga en cuenta que si muestra 'range.Setup (r => r.Column) .Returns (0);' esta prueba también pasará. –

+1

Excelente, gracias! La punta ILSpy también era dorada; en mi proyecto real, veo que aparecen otras propiedades adicionales además de Columna. Los presentes son "Columna", "Columnas", "Fila", "Filas" y "Valor". Este comportamiento probablemente hará que cualquier prueba unitaria que escriba sea bastante quebradiza, porque en cualquier momento pueden aparecer nuevas propiedades y romper algo ... En cualquier caso, al usar sus consejos y burlarse cuidadosamente de todas las propiedades adicionales, funciona, por lo que se marca como respuesta. ¡Gracias Señor! –

Cuestiones relacionadas