Está construindo mocks complexos para testes unitários, um sinal de arquitetura ruim?

5

O título é bastante auto explicativo.

Para elaborar: No momento, estou atualizando um conjunto de testes de unidade para um aplicativo que faz uso pesado do Entity Framework. Nós nos conectamos a isso através de uma interface de repositório clássica para que possa ser ridicularizada.

Não estamos fazendo o teste primeiro (esse é um argumento totalmente diferente, no qual não quero que essa questão se degenere). Em vez disso, um tipo de abordagem "codifique um pouco, teste um pouco". Então, não estamos preenchendo um aplicativo inteiro com testes.

Eu aprecio que um conjunto completo de testes para tal aplicativo provavelmente requer um simulacro de repositório muito complexo. No entanto, acabei de criar uma nova classe de teste e o primeiro teste exigiu um repositório simulado com cerca de 5 funções de obtenção / salvamento do repositório ridicularizado.

Era uma função bastante simples que estava sendo testada. O intervalo de classes simuladas era necessário devido às operações realizadas no construtor da classe e afins.

Tendo feito isso, me ocorreu que isso dificilmente parecia uma unidade. E isso pode ser um sinal de que meu código era muito interdependente. Então: está criando um único teste que exige uma simulação complexa, muitas vezes um sinal de má arquitetura?

    
por Matt Thrower 14.05.2015 / 10:57
fonte

1 resposta

7

Vou ter que fazer algumas suposições aqui

Você menciona o EF, então acho que os mocks em questão estão relacionados ao datalayer?

Como você está usando o EF, acho que o seu Repositório apresenta um IQueryable e seus modelos constroem consultas dentro deles mesmos?

Isso levaria você a ter que criar uma simulação com dados que sejam consistentes com as várias consultas que seus Modelos executam, o que, imagino, pode acabar sendo bastante complicado.

Acho que o erro aqui é o repositório que pode ser consultado. Minha opinião é que os repositórios devem expor métodos como

IEnumerable GetModelsByConditionXAndConditionY (var valueOfAParmeter)

em vez de

IEnumerable GetModelsByQuery (Func SomeQueryFunction)

ou

IQueryable GetModelsButDontReturnThemYetINeedToThink ()

Isso permite que você construa uma versão na memória do seu banco de dados com dados de teste consistentes, porque as maneiras pelas quais esses dados são retornados são conhecidas pelo Repositório.

Qualquer classe Consuming pode pegar o repositório e esperar que ele funcione corretamente sem a configuração específica do modelo dos dados.

Eu também tendem a fazer este repositório simulado como sua própria classe, em vez de usar um framework simulado para configurá-lo por teste unitário

Isso torna seus testes unitários muito simples, pois todos usam os mesmos dados simulados e permitem que você injete os mesmos repositórios simulados em seu aplicativo real para testes de IU, etc.

    
por 14.05.2015 / 11:29
fonte