Domanda

Qualche settimana fa mi sono buttata sul (ComponentModel) carrozzone MEF, e ora sto usando per un sacco di miei plugin e le librerie anche condivise. Nel complesso, è stato grande a parte i frequenti errori da parte mia, che si traducono in sessioni frustranti debug.

In ogni caso, la mia app è stato in esecuzione grande, ma le mie modifiche al codice MEF-correlata hanno causato il mio automatizzato costruisce a fallire. La maggior parte dei miei test di unità sono insufficienti, semplicemente perché i moduli stavo testando erano dipende da altri moduli che dovevano essere caricati dal MEF. Ho lavorato intorno a queste situazioni bypassando MEF e istanziare direttamente quegli oggetti.

In altre parole, via MEF vorrei avere qualcosa di simile

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

e

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

Ma nel mio test di unità, vorrei solo usare

CandyInterface MyCandy = new CandyInterface( "Godiva");

In aggiunta, il CandyInterface richiede una connessione ad un database, che ho lavorato in giro da solo l'aggiunta di un database di test alla mia cartella di test di unità, e non ho l'uso NUnit che, per tutti i test.

Ok, quindi qui sono le mie domande riguardo a questa situazione:

  1. E 'un brutto modo di fare le cose?
  2. Consiglieresti a comporre le parti a [SETUP]
  3. non ho ancora imparato a usare prende in giro in unit testing - è questo un buon esempio di un caso in cui potrei voler deridere la connessione al database sottostante (in qualche modo) per dati fittizi appena di ritorno e non realmente bisogno di un database ?
  4. Se hai incontrato qualcosa di simile prima, si può offrire la vostra esperienza e il modo in cui hai risolto il tuo problema? (O dovrebbe andare questo nella comunità wiki?)
È stato utile?

Soluzione

Sembra che si è sulla strada giusta. Un test di unità dovrebbe provare un Unità , ed è quello che si fa quando si crea direttamente le istanze. Se si lascia MEF comporre le istanze per voi, avrebbero tendere test integrazione . Non che ci sia qualcosa di sbagliato con i test di integrazione, ma unit test tendono ad essere più gestibile, perché si prova ogni unità in isolamento.

Non è necessario un contenitore per cablare casi in unit test .

Io in genere raccomandare contro comporre Infissi durante la configurazione, in quanto porta alla generale Fixture contro -pattern.

E 'best practice per sostituire le dipendenze con test Doppio . irride dinamica è uno dei più versatili modi di fare questo, quindi sicuramente qualcosa che si dovrebbe imparare.

Altri suggerimenti

Sono d'accordo che la creazione delle DOC manualmente è molto meglio che usare contenitore composizione MEF per soddisfare le importazioni, ma per quanto riguarda la nota 'compositing infissi in porta di configurazione per il dispositivo generale modello anti' - voglio ricordare che questo non è sempre il caso .

Se si utilizza il contenitore statico e le importazioni Soddisfare via CompositionInitializer.SatisfyImports si dovrà affrontare il generale dispositivo di anti motivo come CompositionInitializer.Initialize non può essere chiamato più di una volta. Tuttavia, è sempre possibile creare CompositionContainer, aggiungere i cataloghi, e chiamare SatisyImportOnce sul contenitore stesso. In questo caso è possibile utilizzare un nuovo CompositionContainer in ogni prova e farla franca di fronte al comune / dispositivo generale di anti modello

ho bloggato su come fare test di unità (non NUnit, ma funziona lo stesso) con MEF. Il trucco era quello di utilizzare un MockExportProvider e ho creato una base di prova per tutti i miei test per ereditare da.

Questa è la mia funzione AutoWire principale che funziona per test di integrazione e di unità:

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);        
}

Più informazioni sul mio post: https: / /yoavniran.wordpress.com/2012/10/18/unit-testing-wcf-and-mef/

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top