2010-07-02 20 views
6

tengo una clase A, que tiene la siguiente:Moq a MEF Importar?

public class A { 
    [Import(typeof(IMyService)] 
    public IMyService MyService { get; set; } 

    public A() { 
     CompositionInitializer.SatisfyImports(this); 
    } 

    public void DoWork() { 
     //Blah 
     MyService.DoIt(); 
     //Blah 
    } 
} 

y una prueba para probar esto (independiente DLL - obviamente)

[TestMethod] 
public void TestDoWork() { 
    //Blah 
    DoWork(); 
    //Assert assert 
} 

Esta falla como intentar llamar 'MyService' me da nula . entonces he intentado:

[ClassInitialize] 
public void InitialiseClass() { 
    var myService = new Mock<IMyService>(); 
    MyService = myService.Object; 
} 

con 'MyService' declararse como:

[Export(typeof(IMyService))] 
public IMyService MyService { get; set; } 

Pero todavía no hay alegría, me estoy perdiendo algo - es esto posible?

Estoy usando SL3, MEF Preview 9 y MOQ.

Cualquier ayuda apreciada!

Saludos

Chris

Respuesta

4

Su clase debe tener este aspecto:

public class A 
{ 
    private readonly IMyService _myService; 

    [ImportingConstructor] 
    public A(IMyService myService) 
    { 
     _myService = myService; 
    } 

    public void DoWork() { 
     //Blah 
     _myService.DoIt(); 
     //Blah 
    } 
} 

Y la prueba debe tener este aspecto:

[TestMethod] 
public void DoWork_invokes_IMyService_DoIt() 
{ 
    // arrange mock and system under test 
    var myService = new Mock<IMyService>(); 
    var a = new A(myService.Object); 

    // act  
    a.DoWork(); 

    // assert that DoIt() was invoked 
    myService.Verify(x => x.DoIt()); 
} 

El hecho de que se utiliza el MEF no debe ser importante en las pruebas unitarias. MEF solo entra en juego cuando se conectan muchos componentes juntos, que es exactamente lo contrario de lo que sucede en una prueba unitaria. Una prueba unitaria es, por definición, una prueba de un componente aislado.

Editar: si lo prefiere la inyección propiedad, entonces tu clase no necesita un constructor y la parte de los arreglos en su unidad de prueba debe ser similar a esto en su lugar:

var myService = new Mock<IMyService>(); 
    var a = new A(); 
    a.MyService = myService.Object; 
+0

OK, pero ¿por qué necesito usar el importador del constructor, la propiedad funciona bien en mi implementación real, presumiblemente hay una ruta para poder simular esos tipos de importaciones? –

+1

@Chris: aunque MEF fomenta la inyección de propiedades, prefiero la inyección de construcción porque de esa forma el compilador evita que cree objetos con dependencias faltantes. También le permite hacer que los campos de dependencia sean de solo lectura, por lo que no tiene que pensar en lo que sucede si se reemplaza una dependencia. –

+0

He optado por este método, personalmente todavía me gustaría saber si puede burlarse de la inyección de la propiedad, pero esto ayuda a solucionar el problema que tenía. Saludos. –

1

Dónde has añadido [Exportar] para la instancia IMyService, en realidad se han añadido que al contenedor composición? Si no, no participará en la composición. Para añadir un objeto burlado al contenedor, haga lo siguiente:

container.ComposeExportedValue<IMyService>(mock.Object); 

O simplemente:

container.ComposeExportedValue(mock.Object); // type inference. 

Hacer esto antes de crear una instancia de A le permitirá estar compuesto dentro de la Un ejemplo.

+0

que no es necesario añadir la aplicación concreta a un contenedor para conseguir que funcione. Pero veo tu punto. ¿Dónde ves el contenedor? –

0

No deberían encenderse hasta MEF en tus pruebas de unidad. La composición va más allá del alcance de la prueba unitaria, no muy diferente de un contenedor IoC.

dependencias Insted, debe inyectarse requeridos manualmente:

[TestClass] 
public class ATest { 
    Mock<IMyService> myService ; 
    [TestInitialize] 
    public void InitialiseClass() { 
    myService = new Mock<IMyService>(); 
    } 

    [TestMethod] 
    public void DoWorkShouldCallDoIt { 
    A a = new A(); 
    a.MyService = myService.Object; 
    a.DoWork(); 
    myService.Verify(m=>m.DoIt(), Times.Once()); 
    } 
}