Question

Quelques semaines j'ai sauté sur le train en marche MEF (ComponentModel), et je suis maintenant l'utilise pour beaucoup de mes plugins et aussi des bibliothèques partagées. Globalement, il est été super à part les erreurs fréquentes de ma part, qui se traduisent par des sessions de débogage de frustrant.

De toute façon, mon application a fonctionné très bien, mais mes changements de code MEF- connexes ont causé mon automatisé construit à l'échec. La plupart de mes tests unitaires ne parvenaient pas simplement parce que les modules que je testais dépendaient d'autres modules qui doivent être chargés par le MEF. J'ai travaillé autour de ces situations en contournant le MEF et instancier directement ces objets.

En d'autres termes, par l'intermédiaire du MEF j'aurais quelque chose comme

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

et

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

Mais dans mes tests unitaires, je voudrais simplement utiliser

CandyInterface MyCandy = new CandyInterface( "Godiva");

En outre, le CandyInterface nécessite une connexion à une base de données, que j'ai travaillé autour en ajoutant simplement une base de données de test à mon dossier de test unitaire, et je dois utiliser NUnit que pour tous les tests.

Ok, donc voici mes questions concernant cette situation:

  1. Est-ce une mauvaise façon de faire les choses?
  2. recommanderiez-vous la composition des pièces dans [SetUp]
  3. Je n'ai pas encore appris à utiliser se moque dans les tests unitaires - est-ce un bon exemple d'un cas où je pourrais vouloir se moquer de la connexion de base de données sous-jacente (en quelque sorte) aux données fictives juste de retour et pas vraiment besoin d'une base de données ?
  4. Si vous avez rencontré quelque chose comme ça avant, pouvez-vous offrir votre expérience et la façon dont vous avez résolu votre problème? (Ou si cela, aller dans le wiki de la communauté?)
Était-ce utile?

La solution

On dirait que vous êtes sur la bonne voie. Un test unitaire doit tester une unité , et que ce que vous faites lorsque vous créez directement les instances. Si vous laissez les instances pour composer MEF vous, ils auraient tendance à des tests intégration . Non pas qu'il n'y a rien de mal avec les tests d'intégration, mais les tests unitaires ont tendance à être plus maintenable parce que vous testez chaque unité séparément.

Vous n'avez pas besoin d'un conteneur pour câbler cas dans les tests unitaires .

Je recommande généralement contre la composition de luminaires à tubes dans SetUp, car elle conduit à la générale Fixture de la lutte contre -pattern.

Il est la meilleure pratique pour remplacer les dépendances avec test double. raille dynamique est l'un des plus polyvalents façons de le faire, donc certainement quelque chose que vous devriez apprendre.

Autres conseils

Je suis d'accord que la création du DOCs est manuellement beaucoup mieux que d'utiliser conteneur de composition MEF pour satisfaire les importations, mais en ce qui concerne la note « accessoires compositing en fils de configuration du dispositif général de signatures anti » - Je veux dire que ce n'est pas toujours le cas .

Si vous utilisez le conteneur statique et les importations absorbent via CompositionInitializer.SatisfyImports vous devrez faire face au modèle générale anti calendier en CompositionInitializer.Initialize ne peut pas être appelé plus d'une fois. Cependant, vous pouvez toujours créer CompositionContainer, ajouter des catalogues, et appelez SatisyImportOnce sur le conteneur lui-même. Dans ce cas, vous pouvez utiliser une nouvelle CompositionContainer dans tous les tests et s'en face du modèle partagé contre / montage général

Je blogué sur la façon de faire des tests unitaires (non nunit mais fonctionne tout de même) avec MEF. L'astuce était d'utiliser un MockExportProvider et je créé une base de test pour tous mes tests d'hériter.

Ceci est ma principale fonction autowire qui fonctionne pour les tests d'intégration et de l'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);        
}

Plus d'infos sur mon message: https: / /yoavniran.wordpress.com/2012/10/18/unit-testing-wcf-and-mef/

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top