Eu tenho vários métodos de lógica de negócios que armazenam e recuperam (com filtragem) objetos e listas de objetos do cache.
Considerar
IList<TObject> AllFromCache() { ... }
TObject FetchById(guid id) { ... }
IList<TObject> FilterByPropertry(int property) { ... }
Fetch..
e Filter..
chamaria o AllFromCache
que preencheria o cache e retornaria se não estiver lá e retornaria apenas se estiver.
Eu geralmente evito testar essas unidades. Quais são as práticas recomendadas para o teste de unidade nesse tipo de estrutura?
Eu considerei preencher o cache no TestInitialize e removê-lo no TestCleanup, mas isso não parece certo para mim (embora possa ser).
fonte
O Princípio da Responsabilidade Única é seu melhor amigo aqui.
Primeiro, mova AllFromCache () para uma classe de repositório e chame-a GetAll (). A recuperação do cache é um detalhe de implementação do repositório e não deve ser conhecido pelo código de chamada.
Isso torna fácil e fácil testar sua classe de filtragem. Não se importa mais de onde você está conseguindo.
Segundo, agrupe a classe que obtém os dados do banco de dados (ou qualquer outro local) em um wrapper de cache.
AOP é uma boa técnica para isso. É uma das poucas coisas em que é muito bom.
Usando ferramentas como o PostSharp , você pode configurá-lo para que qualquer método marcado com um atributo escolhido seja armazenado em cache. No entanto, se essa é a única coisa que você está armazenando em cache, não precisa ir tão longe quanto ter uma estrutura de AOP. Apenas tenha um Repositório e um Caching Wrapper que usem a mesma interface e os injetem na classe de chamada.
por exemplo.
Veja como você removeu o conhecimento de implementação do repositório do ProductManager? Veja também como você aderiu ao Princípio de Responsabilidade Única ao ter uma classe que lida com extração de dados, uma classe que lida com recuperação de dados e uma classe que lida com cache.
Agora você pode instanciar o ProductManager com um desses repositórios e obter o cache ... ou não. Isso é incrivelmente útil mais tarde, quando você recebe um bug confuso que suspeita ser resultado do cache.
(Se você estiver usando um contêiner de COI, melhor ainda. Deve ser óbvio como se adaptar.)
E, em seus testes do ProductManager
Não há necessidade de testar o cache.
Agora a pergunta é: devo testar esse CachedProductRepository? Eu sugiro que não. O cache é bastante indeterminado. A estrutura faz coisas que estão fora de seu controle. Por exemplo, basta remover coisas dele quando estiver muito cheia, por exemplo. Você terminará com testes que falharão uma vez na lua azul e nunca entenderá realmente o porquê.
E, tendo feito as alterações sugeridas acima, não há realmente muita lógica para testar lá. O teste realmente importante, o método de filtragem, estará lá e completamente abstraído dos detalhes de GetAll (). GetAll () apenas ... recebe tudo. De algum lugar.
fonte
Sua abordagem sugerida é o que eu faria. De acordo com sua descrição, o resultado do método deve ser o mesmo, independentemente de o objeto estar presente no cache ou não: você ainda deve obter o mesmo resultado. É fácil testar, configurando o cache de uma maneira específica antes de cada teste. Provavelmente existem alguns casos adicionais, como se o guid é
null
ou nenhum objeto possui a propriedade solicitada; esses também podem ser testados.Além disso, você pode considerar que o objeto esteja presente no cache após o retorno do método, independentemente de ele estar no cache em primeiro lugar. Isso é controverso, pois algumas pessoas (inclusive eu) argumentam que você se preocupa com o que recebe da sua interface, não como obtê-lo (ou seja, com o teste de que a interface funciona conforme o esperado, e não com uma implementação específica). Se você considerar importante, terá a oportunidade de testar isso.
fonte
Na verdade, essa é a única maneira correta de fazer. É para isso que essas duas funções existem: definir as pré-condições e limpar. Se as pré-condições não forem atendidas, seu programa poderá não funcionar.
fonte
Eu estava trabalhando em alguns testes que usam cache recentemente. Criei um wrapper em torno da classe que funciona com o cache e, em seguida, tinha afirmações de que esse wrapper estava sendo chamado.
Fiz isso principalmente porque a classe existente que trabalha com cache era estática.
fonte
Parece que você deseja testar a lógica de armazenamento em cache, mas não a lógica de preenchimento. Então, eu sugiro que você zombe do que não precisa testar - preenchendo.
Seu
AllFromCache()
método cuida de preencher o cache e isso deve ser delegado para outra coisa, como um fornecedor de valores. Portanto, seu código seria semelhanteAgora você pode zombar do fornecedor para o teste, para retornar alguns valores predefinidos. Dessa forma, você pode testar sua filtragem e busca reais e não carregar objetos.
fonte