Faking - Dependência vs Detalhes Internos

5

Apenas por uma questão de discussão abaixo, quando me refiro a zombaria, quero dizer zombando / stubbing / faking, como contraste para usar a implementação real no teste

Acabei de discutir com meu colega durante uma sessão de programação em pares sobre se deveríamos usar o mocking em testes de unidade para nosso próprio código escrito. (Não tenho certeza se isso é importante, mas estamos programando em pares em uma base de código Ruby / Rails)

Seu argumento é que não devemos usar zombaria se for nosso próprio código escrito. Zombar deve ser usado apenas para distribuir dependências externas (por exemplo, sistema de terceiros). Digamos que se houver classes A e B, e A depende de B (um dos métodos de A cria e usa B), ele disse que não devemos zombar de B quando testamos A (ambos A e B são escritos e mantidos por nós) ), uma vez que B é detalhes internos de implementação de A.

Embora eu concorde com ele até certo ponto, ainda encontro alguns casos em que debater nosso próprio código é necessário e necessário:

  • Primeiro, acredito que, se não zombarmos das dependências de uma classe, não será mais um teste de unidade. Assim, como no exemplo acima, estamos escrevendo um teste de integração para as classes A e B. Não estou dizendo que os testes de integração não são necessários, mas há algumas desvantagens em relação ao teste unitário, por exemplo. executar mais lentamente e quando um teste falhar, você precisará rastrear o código de implementação para identificar os componentes que causam a falha. E, portanto, devemos deixar claro o que é teste de unidade, o que é teste de integração
  • Em segundo lugar, não devemos testar e nos preocupar com detalhes de implementação de uma classe, desde que seu contrato público ainda seja mantido. No entanto, acredito que devemos testar a interação de uma classe com suas dependências (pares), já que essas interações são comportamentos esperados dessa classe. Em alguns casos, não é fácil determinar o que é detalhes de implementação e o que é dependência, por exemplo. em um aplicativo em camadas (controlador - > serviço de aplicativo - > domínio), é uma dependência de serviço de aplicativo ou implementação interna de um controlador?

Então, minhas perguntas são:

  • Quais são suas opiniões sobre quando e onde usar o escárnio?
  • Alguma boa heurística para decidir o que é dependência e o que é detalhes internos de implementação? Tomemos por exemplo o aplicativo em camadas acima

Não tenho certeza se é porque meu histórico é em C #, acho difícil aceitar que a ideia de zombaria não seja necessária ao testar nosso próprio código

    
por Phuong Nguyen 17.10.2016 / 14:45
fonte

3 respostas

2

His argument is that we should not use mocking if it's our own written code. Mocking should be used only to stuffs out external dependencies (.e.g. third party system)

O uso de mock deve ser usado apenas se for absolutamente necessário, já que cada simulação significa que você está testando como um pedaço de código se comporta quando conectado a essa simulação, em vez do código real.

Veja Pare de usar mocks , juntamente com Mude-se, não os seus testes e muitos mais artigos pesquisados facilmente sobre o motivo pelo qual o escárnio deve ser evitado.

Let's say if there are class A and B, and A depends on B (.e.g. one of A's method creates and uses B)

B é uma classe pública? Em caso afirmativo, A não deveria criar uma instância de B ; isso é acoplamento apertado. Em vez disso, A deve receber uma instância da interface IB , ou IBFactory , a partir do qual pode solicitar uma IB instance. Se B for bem comportado com comportamento determinístico e nenhum efeito colateral externo, ele poderá até mesmo ser usado diretamente ao testar A .

First, I believe if we don't mock dependencies of a class, it's no longer unit test.

Desculpe, mas isso é um absurdo. Um teste unitário é um teste de uma unidade de código que pode ser executado em paralelo com outros testes sem afetar esses testes e sem efeitos colaterais externos. Essa unidade de código pode ser uma função, uma coleção de funções (por exemplo, uma classe) ou quase todo o sistema, desde que não tenha efeitos colaterais ou afete outros testes.

What are your opinions on when and where to use mocking?

Você usa zombaria apenas quando não pode ser evitado.

Any good heuristics to decide what is dependency and what is internal implementation details?

A dependência é pública? Se sim, então não é um detalhe de implementação. Se não for público, então é realmente um detalhe de implementação, mas também é uma dependência (e se for um detalhe de implementação, não deve ser ridicularizado, pois os testes não devem chegar perto dos detalhes de implementação).

    
por 17.10.2016 / 15:14
fonte
1

Existem três bons argumentos para usar Mocks (e por mocks, quero dizer, aqueles itens criados por um framework como o Mocha, que permite afirmar se o mock foi chamado):

  • É importante saber que o objeto em teste corretamente e consistentemente chama o outro objeto de uma maneira específica e / ou um número específico de vezes.
  • É importante evitar os efeitos colaterais causados pela chamada de outros métodos de objeto.
  • É importante isolar a unidade de código que você quer testar para identificar a causa das falhas, como aponta @Callum em seu comentário sobre a resposta de David Arno.

Se você não se importa com esses itens, Mocks não são realmente necessários.

    
por 17.10.2016 / 21:45
fonte
1

C # fundo aqui também. Você pode querer procurar a abordagem “mockista” (também conhecida como London) para o TDD (em oposição ao clássico / Detroit). Pessoalmente, usei-o com grande sucesso em muitos projetos comerciais e descobri que é a melhor maneira de testar minhas unidades em perfeito isolamento. Você acaba com um design surpreendentemente desacoplado dessa maneira.

Não dê ouvidos a pessoas que lhe dizem para confiar em testes de integração. Testes de integração são uma farsa , porque não há nenhuma maneira de cobrir todas as combinações de casos de borda dentro da cadeia de unidades que seu teste de integração está supostamente testando. Concentre-se em ter unidades testadas com perfeição e todo o sistema funcionará apenas quando você compuser seu gráfico de objeto (normalmente, incluo alguns testes de integração como teste de integridade).

Eu recomendo o seguinte livro, especialmente os primeiros capítulos que explicam a abordagem mockista do TDD perfeitamente: Software Orientado a Objetos em Crescimento, Guiado por Testes

Quanto à sua pergunta sobre o que zombar? Eu zombei de tudo que não está sob o teste. Geralmente isso significa zombar das interfaces das dependências que estão sendo injetadas no construtor da classe que está sendo testada na unidade. Com o C #, temos a vantagem de ter acesso ao Moq, que não é apenas muito poderoso, mas também muito conciso e legível.

    
por 19.10.2016 / 04:06
fonte