Pergunta

Algumas semanas atrás eu entrei no MEF (ComponentModel) onda, e agora estou usando-o para um monte de meus plugins e também bibliotecas compartilhadas.No geral, foi muito bom além dos frequentes erros da minha parte, que resultam em frustrante sessões de depuração.

De qualquer maneira, meu app foi o ótimo, mas o meu MEF relacionados a alterações de código de ter causado a minha automatizado constrói a falhar.A maioria dos meus testes de unidade falhar, simplesmente porque os módulos que eu estava testando estavam dependentes de outros módulos que precisava ser carregado pelo MEF.Eu trabalhava em torno destas situações, ignorando MEF e diretamente instanciar os objetos.

Em outras palavras, via MEF, eu teria algo como

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

e

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

Mas em meus testes de unidade, gostaria apenas de uso

CandyInterface MyCandy = new CandyInterface( "Godiva");

Além disso, o CandyInterface requer uma conexão com um banco de dados, o que eu tenho contornado adicionando apenas um banco de dados de teste para a minha unidade pasta de teste, e eu tenho o NUnit uso que para todos os testes.

Ok, então aqui estão as minhas perguntas com relação a esta situação:

  1. Esta é uma Má Maneira de fazer as coisas?
  2. Você recomendaria a compor peças em [SetUp]
  3. Eu ainda não aprendeu a usar as simulações de teste de unidade -- este é um bom exemplo de um caso onde eu poderia querer zombar do banco de dados subjacente de ligação (de alguma forma) para retornar dados fictícios e não realmente necessitam de um banco de dados?
  4. Se você encontrou algo como isso antes, você pode oferecer a sua experiência e a forma como você resolveu o seu problema?(ou, em caso de ir para a comunidade wiki?)
Foi útil?

Solução

Parece que você está no caminho certo.Uma unidade de teste deve testar um unidade, e isso é o que você faz quando você criar instâncias.Se você deixar o MEF compor instâncias para você, eles tendem para testes de integração.Não que haja algo de errado com testes de integração, mas testes de unidade tendem a ser mais fácil porque você teste cada unidade de isolamento.

Você não precisa de um recipiente para o fio até a instâncias de testes de unidade.

Eu geralmente recomendo contra a compor Luminárias na Instalação, pois leva à Geral De Fixação anti-padrão.

Ele é a melhor prática para substituir dependências com Teste De Dobra.Dinâmica zomba é um dos mais versáteis formas de se fazer isso, então definitivamente algo que você deve aprender.

Outras dicas

Concordo que criar os documentos manualmente é muito melhor do que usar o contêiner de composição MEF para satisfazer as importações, mas com relação à nota 'equipamentos de composição na configuração leva ao acessório geral anti -padrão' - quero mencionar que esse nem sempre é o caso.

Se você estiver usando o contêiner estático e satisfazer as importações via compositionInitializer.satisfyimports, você terá que enfrentar o anti -padrão geral como compositionInitializer.initialize não poderá ser chamado mais de uma vez. No entanto, você sempre pode criar o CompositionContainer, adicionar catálogos e chamar SatisyimportOnce no próprio contêiner. Nesse caso, você pode usar um novo CompositionContainer em todos os testes e se safar de enfrentar o anti -padrão compartilhado/geral

Eu escrevi no blog sobre como fazer testes de unidade (não frenit, mas funciona da mesma forma) com o MEF. O truque era usar um MockexportProvider e eu criei uma base de teste para todos os meus testes para herdar.

Esta é a minha principal função AutoWire que funciona para testes de integração e unidade:

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

Mais informações sobre minha postagem: https://yoavniran.wordpress.com/2012/10/18/unit-testing-wcf-and-sef/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top