Frage

Vor ein paar Wochen habe ich auf dem MEF (Component) Zug aufgesprungen, und ich benutze es jetzt viele meiner Plugins und gemeinsam genutzte Bibliotheken auch. Insgesamt ist es grossartig, abgesehen von den häufigen Fehlern meinerseits, die in frustrierend Debug-Sitzungen führen.

Wie auch immer, meine app hat große läuft, aber meine MEF-bezogenen Code-Änderungen verursacht haben meine automatisierten Builds zum Scheitern verurteilt. Die meisten meiner Unit-Tests versagten, nur weil die Module I-Tests wurde auf andere Module abhängig waren, die von MEF geladen werden musste. Ich arbeitete um diese Situationen von MEF zu umgehen und direkt die Objekte instanziieren.

Mit anderen Worten, über MEF Ich würde so etwas habe

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

und

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

Aber in meinen Unit-Tests, würde ich nur verwenden

CandyInterface MyCandy = new CandyInterface( "Godiva");

Darüber hinaus erfordert die CandyInterface eine Verbindung zu einer Datenbank, die ich gearbeitet habe, indem einfach eine Testdatenbank zu meinen Einheit Testordnern um, und ich habe die Verwendung NUnit, dass für alle Tests.

Ok, also hier sind meine Fragen zu dieser Situation:

  1. Ist das ein schlechter Weg, Dinge zu tun?
  2. Würden Sie Teile in [Setup] Komponieren
  3. Ich habe noch nicht gelernt, wie Mocks in Unit-Tests verwenden - dies ist ein gutes Beispiel für einen Fall, wo ich will vielleicht die zugrunde liegende Datenbankverbindung (irgendwie) nur Rückkehr Dummy-Daten spotten und nicht wirklich eine Datenbank benötigen ?
  4. Wenn Sie so etwas wie dies zuvor begegnet sind, können Sie bieten Ihre Erfahrungen und die Art und Weise Sie Ihr Problem gelöst? (Oder sollte diese gehen in die Community Wiki?)
War es hilfreich?

Lösung

Es klingt wie Sie auf dem richtigen Weg sind. Ein Unit-Test sollte prüfen, eine Einheit , und das ist, was Sie tun, wenn Sie direkt Instanzen erstellen. Wenn Sie MEF-Instanzen für Sie zusammenstellen lassen, würden sie dazu neigen, in Richtung Integrationstests . Nicht, dass etwas falsch gibt es mit Integrationstests, aber Unit-Tests sind in der Regel besser verwaltbar sein, weil Sie jede Einheit einzeln testen.

Sie brauchen keine Container-Instanzen in Unit-Tests verkabeln .

Generell empfehle ich gegen Befestigungen in SetUp Komponieren, wie es führt zu den Allgemeinen Fixture anti -Muster.

Am besten ist es Praxis Abhängigkeiten zu ersetzen mit Test-Double . Dynamische Mocks ist eine der vielseitigere Möglichkeiten dies zu tun, also auf jeden Fall etwas, das man lernen sollte.

Andere Tipps

Ich bin damit einverstanden, dass Sie die Dokumentation manuell zu erstellen ist viel besser als MEF Zusammensetzung Behälter mit Importen zu erfüllen, aber in Bezug auf die Note ‚Compositing Leuchten in Setup führt zur allgemeinen Befestigung Anti-Pattern‘ - Ich möchte erwähnen, dass das nicht immer der Fall, .

Wenn Sie die statischen Container und satisfy Importe über CompositionInitializer.SatisfyImports verwenden werden Sie das allgemeine Befestigung Anti-Muster als CompositionInitializer.Initialize zu kämpfen haben kann nicht mehr aufgerufen werden als einmal. Sie können jedoch immer CompositionContainer erstellen, fügen Sie Kataloge und rufen SatisyImportOnce auf den Behälter selbst. In diesem Fall, dass Sie einen neuen CompositionContainer in jedem Test verwenden können, und weg mit Blick auf das gemeinsame / allgemeine Befestigung anti Muster

ich gebloggt, wie Unit-Tests zu tun (nicht nUnit funktioniert aber nur das gleiche) mit MEF. Der Trick war eine MockExportProvider zu verwenden, und ich erstellt eine Testbasis für alle meine Tests zu vererben.

Das ist mein Haupt AutoWire Funktion, dass die Arbeiten für die Integration und Unit-Tests:

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

Weitere Informationen über meinen Beitrag: https: / /yoavniran.wordpress.com/2012/10/18/unit-testing-wcf-and-mef/

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top