Pregunta

Hace unas semanas me subieron al carro MEF (ComponentModel), y ahora estoy usando para muchos de mis plugins y bibliotecas también compartidos. En general, ha sido genial, aparte de los errores frecuentes en mi parte, que se traducen en sesiones frustrantes depuración.

De todos modos, mi aplicación ha estado funcionando muy bien, pero mis cambios de código MEF relacionada haber causado mi automatizado construye a fallar. La mayoría de mis pruebas de unidad fallaban simplemente porque los módulos que estaba probando dependían de otros módulos que necesitaban ser cargado por el MEF. He trabajado en torno a estas situaciones sin pasar por el MEF y crear instancias directamente dichos objetos.

En otras palabras, a través del MEF Me gustaría tener algo como

[Import]
public ICandyInterface ci { get; set; }

y

[Export(typeof(ICandyInterface))]
public class MyCandy : ICandyInterface
{
    [ImportingConstructor]
    public MyCandy( [Import("name_param")] string name) {}
    ...
}

Pero en mis pruebas de unidad, sólo usaría

CandyInterface MyCandy = new CandyInterface( "Godiva");

Además, el CandyInterface requiere una conexión a una base de datos, que he trabajado en todo con sólo añadir una base de datos de prueba a mi carpeta de prueba de unidad, y tengo uso NUnit que, para todas las pruebas.

Ok, así que aquí están mis preguntas con respecto a esta situación:

  1. ¿Es esta una mala manera de hacer las cosas?
  2. ¿Recomendado por partes en [Configuración] componer
  3. I aún no han aprendido a utilizar se burla de la unidad de pruebas - es este un buen ejemplo de un caso en el que podría querer burlarse de la conexión de base de datos subyacente (de alguna manera) a datos ficticios acaba de retorno y en realidad no requiere una base de datos ?
  4. Si usted ha encontrado algo como esto antes, puede ofrecer su experiencia y la forma en que resolvió su problema? (O debería pasar esto en el wiki de la comunidad?)
¿Fue útil?

Solución

Parece que usted está en el camino correcto. Una prueba de la unidad debe probar un unidad , y eso es lo que hacen cuando se crea directamente casos. Si deja que el MEF componer casos para usted, tenderían hacia pruebas integración . No es que haya nada malo con las pruebas de integración, pruebas unitarias, pero tienden a ser más fácil de mantener porque se prueba cada unidad de forma aislada.

No es necesario un recipiente que cablear los casos en las pruebas de unidad .

En general, recomiendo contra componer accesorios en la configuración, ya que conduce a la lucha contra la general Fixture -pattern.

Es una buena práctica para reemplazar dependencias con prueba de dobles . burla dinámico es uno de los más versátiles maneras de hacer esto, por lo que definitivamente algo que usted debe aprender.

Otros consejos

Me acuerdo en que la creación de los documentos de forma manual es mucho mejor que el uso de contenedores composición MEF para satisfacer las importaciones, pero con respecto a la nota 'de composición accesorios en las derivaciones de configuración para el dispositivo general contra el patrón' - Quiero mencionar que eso no es siempre el caso .

Si está utilizando el contenedor estático y las importaciones suponen través CompositionInitializer.SatisfyImports que tendrá que afrontar el accesorio contra el patrón general CompositionInitializer.Initialize no puede ser llamado más de una vez. Sin embargo, siempre se puede crear CompositionContainer, agregar catálogos, y llamar a SatisyImportOnce en el propio envase. En ese caso se puede utilizar un nuevo CompositionContainer en cada prueba y salirse con la cara al accesorio compartida / patrón general contra

Me escribió en su blog acerca de cómo hacer las pruebas unitarias (no nUnit pero funciona de la misma) con el MEF. El truco consistía en utilizar un MockExportProvider y yo creamos una base de prueba para todas mis pruebas a heredar de.

Esta es mi función principal Autowire que las obras para las pruebas de integración y de unidad:

protected void AutoWire(MockExportProvider mocksProvider, params Assembly[] assemblies){

CompositionContainer container = null;

var assCatalogs = new List<AssemblyCatalog>();

foreach(var a in assemblies)
{
    assCatalogs.Add(new AssemblyCatalog(a));
}

if (mocksProvider != null)
{
    var providers = new List<ExportProvider>();

    providers.Add(mocksProvider); //need to use the mocks provider before the assembly ones            

    foreach (var ac in assCatalogs)
    {
        var assemblyProvider = new CatalogExportProvider(ac);                    
        providers.Add(assemblyProvider);
    }

    container = new CompositionContainer(providers.ToArray());

    foreach (var p in providers) //must set the source provider for CatalogExportProvider back to the container (kinda stupid but apparently no way around this)
    {
        if (p is CatalogExportProvider)
        {
            ((CatalogExportProvider)p).SourceProvider = container;
        }
    }
}
else
{
    container = new CompositionContainer(new AggregateCatalog(assCatalogs));
}

container.ComposeParts(this);        
}

Más información en mi post: https: / /yoavniran.wordpress.com/2012/10/18/unit-testing-wcf-and-mef/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top