Sei como uso esses termos, mas estou me perguntando se existem definições aceitas para falsificação , zombaria e stub para testes de unidade? Como você os define para seus testes? Descreva as situações em que você pode usar cada uma.
Aqui está como eu os uso:
Falso : uma classe que implementa uma interface, mas contém dados fixos e nenhuma lógica. Simplesmente retorna dados "bons" ou "ruins", dependendo da implementação.
Mock : uma classe que implementa uma interface e permite a capacidade de definir dinamicamente os valores para retornar / exceções a serem lançadas de métodos específicos e fornece a capacidade de verificar se métodos específicos foram chamados / não chamados.
Stub : Como uma classe simulada, exceto que ela não fornece a capacidade de verificar se os métodos foram chamados / não chamados.
Zombarias e stubs podem ser gerados manualmente ou gerados por uma estrutura de simulação. Classes falsas são geradas manualmente. Uso mocks principalmente para verificar as interações entre minha classe e as classes dependentes. Uso stubs depois de verificar as interações e testar caminhos alternativos através do meu código. Eu uso classes falsas principalmente para abstrair dependências de dados ou quando zombarias / stubs são muito entediantes para serem configurados a cada vez.
fonte
Respostas:
Você pode obter algumas informações:
De Martin Fowler sobre Mock and Stub
Objetos falsos realmente têm implementações de trabalho, mas geralmente usam algum atalho que os torna inadequados para produção
Os stubs fornecem respostas prontas para as chamadas feitas durante o teste, geralmente não respondendo a nada fora do que está programado para o teste. Os stubs também podem registrar informações sobre chamadas, como um stub de gateway de e-mail que lembra as mensagens "enviadas" ou talvez apenas quantas mensagens foram "enviadas".
Zombamos é o que estamos falando aqui: objetos pré-programados com expectativas que formam uma especificação das chamadas que eles devem receber.
De xunitpattern :
Falso : Adquirimos ou construímos uma implementação muito leve da mesma funcionalidade fornecida por um componente do qual o SUT depende e instruímos o SUT a usá-lo em vez do real.
Stub : Esta implementação está configurada para responder a chamadas do SUT com os valores (ou exceções) que exercitarão o Código Não Testado (consulte Erros de Produção na página X) no SUT. Uma indicação importante para o uso de um stub de teste é ter o código não testado causado pela incapacidade de controlar as entradas indiretas do SUT
Objeto simulado que implementa a mesma interface que um objeto do qual o SUT (Sistema em teste) depende. Podemos usar um Objeto Simulado como um ponto de observação quando precisamos fazer a Verificação de Comportamento para evitar que um Requisito Não Testado (consulte Bugs de Produção na página X) seja causado por uma incapacidade de observar efeitos colaterais de métodos de chamada no SUT.
Pessoalmente
Eu tento simplificar usando: Mock e Stub. Uso Mock quando é um objeto que retorna um valor definido para a classe testada. Eu uso o Stub para imitar uma classe Interface ou Resumo a ser testada. De fato, não importa realmente como você chama, são todas as classes que não são usadas na produção e são usadas como classes de utilidade para teste.
fonte
Stub - um objeto que fornece respostas predefinidas para chamadas de método.
Mock - um objeto no qual você define expectativas.
Falso - um objeto com recursos limitados (para fins de teste), por exemplo, um serviço da web falso.
Teste duplo é o termo geral para stubs, zombarias e falsificações. Mas, informalmente, você costuma ouvir as pessoas simplesmente chamá-las de zombaria.
fonte
EXPECT_CALL()
s em um método simulado que força certas saídas com base em determinadas entradas, usando o tipo.WillOnce(Invoke(my_func_or_lambda_func))
(ou com.WillRepeatedly()
) sintaxe anexada a umEXPECT_CALL()
. Alguns exemplos de usoInvoke()
podem ser vistos em um contexto diferente na parte inferior da minha resposta longa aqui: stackoverflow.com/a/60905880/4561887 .Invoke()
está aqui: github.com/google/googletest/blob/master/googlemock/docs/… . De qualquer forma, a conclusão é: o Google mock (gmock) permite criar facilmente zombarias e stubs , embora a maioria das zombarias não sejam stubs.Surpreende-me que essa pergunta já exista há tanto tempo e ninguém ainda tenha fornecido uma resposta baseada em "A arte de testar a unidade", de Roy Osherove .
Em "3.1 Introdução de stubs", define um stub como:
E define a diferença entre stubs e zombarias como:
Falso é apenas o nome usado para stubs e zombarias. Por exemplo, quando você não se importa com a distinção entre stubs e zombarias.
A maneira como o Osherove's distingue stubs e zombes significa que qualquer classe usada como falsa para teste pode ser tanto um stub quanto uma farsa. O que é para um teste específico depende inteiramente de como você faz as verificações em seu teste.
Exemplo de teste em que a classe FakeX é usada como um esboço:
A
fake
instância é usada como um stub porqueAssert
não usa defake
jeito nenhum.Exemplo de teste em que a classe de teste X é usada como uma farsa:
Nesse caso, o
Assert
valor é verificadofake
, fazendo com que seja falso.Agora, é claro que esses exemplos são altamente planejados, mas vejo grande mérito nessa distinção. Isso o torna ciente de como você está testando suas coisas e onde estão as dependências do seu teste.
Eu concordo com Osherove que
Afirmar contra o falso é algo que você realmente deseja evitar, pois torna seus testes altamente dependentes da implementação de uma classe que não é a que está sendo testada. O que significa que os testes para a classe
ActualClassUnderTest
podem começar a ser interrompidos porque a implementação foiClassUsedAsMock
alterada. E isso me dá um cheiro ruim. Os testes paraActualClassUnderTest
, de preferência, devem apenas interromper quandoActualClassUnderTest
são alterados.Sei que escrever afirmações contra o falso é uma prática comum, especialmente quando você é um tipo mockista de assinante TDD. Acho que estou firmemente com Martin Fowler no campo dos classicistas (veja "Mocks are Stubs", de Martin Fowler ) e, como Osherove, evita os testes de interação (o que só pode ser feito com a afirmação contra o falso), tanto quanto possível.
Para uma leitura divertida sobre por que você deve evitar zombarias, conforme definido aqui, pesquise no Google por "classicista mockista fowler". Você encontrará uma infinidade de opiniões.
fonte
Conforme mencionado pela resposta mais votada, Martin Fowler discute essas distinções em Mocks Ar not Stubs e, em particular, no subtítulo The Difference Between Mocks and Stubs , portanto, leia esse artigo.
Em vez de focar em como essas coisas são diferentes, acho mais esclarecedor focar no motivo de esses serem conceitos distintos. Cada um existe para um propósito diferente.
Fakes
Um falso é uma implementação que se comporta "naturalmente", mas não é "real". Estes são conceitos difusos e, portanto, pessoas diferentes têm entendimentos diferentes sobre o que torna as coisas falsas.
Um exemplo de falsificação é um banco de dados na memória (por exemplo, usando o sqlite na
:memory:
loja). Você nunca usaria isso para produção (já que os dados não são persistentes), mas é perfeitamente adequado como banco de dados para uso em um ambiente de teste. Também é muito mais leve que um banco de dados "real".Como outro exemplo, talvez você use algum tipo de armazenamento de objetos (por exemplo, Amazon S3) na produção, mas em um teste você pode simplesmente salvar objetos em arquivos no disco; então sua implementação "salvar em disco" seria falsa. (Ou você pode até fingir a operação "salvar em disco" usando um sistema de arquivos na memória.)
Como terceiro exemplo, imagine um objeto que fornece uma API de cache; um objeto que implementa a interface correta, mas que simplesmente não executa armazenamento em cache, mas sempre retorna um erro de cache, seria uma espécie de falso.
O objetivo de uma falsificação não é afetar o comportamento do sistema em teste , mas sim simplificar a implementação do teste (removendo dependências desnecessárias ou pesadas).
Stubs
Um stub é uma implementação que se comporta "de maneira não natural". É pré-configurado (geralmente pela configuração do teste) para responder a entradas específicas com saídas específicas.
O objetivo de um stub é colocar seu sistema em teste em um estado específico. Por exemplo, se você estiver gravando um teste para algum código que interaja com uma API REST, poderá remover a API REST com uma API que sempre retorne uma resposta fixa ou que responda a uma solicitação de API com um erro específico. Dessa forma, você pode escrever testes que façam afirmações sobre como o sistema reage a esses estados; por exemplo, testando a resposta que seus usuários recebem se a API retornar um erro 404.
Um stub geralmente é implementado para responder apenas às interações exatas às quais você pediu. Mas o principal recurso que faz de algo um stub é seu objetivo : um stub é sobre como configurar seu caso de teste.
Zombaria
Um mock é semelhante a um stub, mas com a verificação adicionada. O objetivo de um mock é fazer afirmações sobre como o sistema em teste interagiu com a dependência .
Por exemplo, se você estiver escrevendo um teste para um sistema que carrega arquivos em um site, você pode criar uma simulação que aceita um arquivo e que pode ser usada para afirmar que o arquivo carregado estava correto. Ou, em uma escala menor, é comum usar uma simulação de um objeto para verificar se o sistema em teste chama métodos específicos do objeto simulado.
As simulações estão vinculadas ao teste de interação , que é uma metodologia de teste específica. As pessoas que preferem testar o estado do sistema em vez de interações com o sistema usarão zombarias com moderação, se houver.
Duplas de teste
Falsificações, stubs e zombarias pertencem à categoria de duplas de teste . Um teste duplo é qualquer objeto ou sistema que você usa em um teste, em vez de outra coisa. A maioria dos testes automatizados de software envolve o uso de testes duplos de algum tipo ou de outro. Alguns outros tipos de duplas de teste incluem valores fictícios , espiões , e I / O blackholes .
fonte
Para ilustrar o uso de stubs e zombarias, também gostaria de incluir um exemplo baseado em " A arte de testar unidades ", de Roy Osherove .
Imagine, temos um aplicativo LogAnalyzer que tem a única funcionalidade de imprimir logs. Ele não precisa apenas falar com um serviço da Web, mas se o serviço da Web gerar um erro, o LogAnalyzer precisará registrar o erro em uma dependência externa diferente, enviando-o por email ao administrador do serviço da Web.
Aqui está a lógica que gostaríamos de testar dentro do LogAnalyzer:
Como você testa se o LogAnalyzer chama o serviço de email corretamente quando o serviço da Web lança uma exceção? Aqui estão as perguntas que enfrentamos:
Como podemos substituir o serviço da web?
Como podemos simular uma exceção do serviço da web para testar a chamada para o serviço de email?
Como saberemos que o serviço de email foi chamado corretamente ou de todo?
Podemos lidar com as duas primeiras perguntas usando um esboço para o serviço da web . Para resolver o terceiro problema, podemos usar um objeto simulado para o serviço de email .
Uma falsificação é um termo genérico que pode ser usado para descrever um esboço ou uma simulação. Em nosso teste, teremos duas falsificações. Um deles será o mock do serviço de email, que usaremos para verificar se os parâmetros corretos foram enviados ao serviço de email. O outro será um esboço que usaremos para simular uma exceção lançada do serviço da web. É um esboço porque não usaremos o serviço da web falso para verificar o resultado do teste, apenas para garantir que o teste seja executado corretamente. O serviço de email é uma farsa, porque afirmaremos que foi chamado corretamente.
fonte
o que você afirma sobre ele é chamado de objeto simulado e tudo o mais que ajudou no teste, é um esboço .
fonte
É uma questão de tornar os testes expressivos. Defino as expectativas em uma simulação, se quero que o teste descreva um relacionamento entre dois objetos. Eu stub valores de retorno se estou configurando um objeto de suporte para me levar ao comportamento interessante no teste.
fonte
Se você estiver familiarizado com Arrange-Act-Assert, uma maneira de explicar a diferença entre stub e mock que pode ser útil para você é que os stubs pertencem à seção de organização, assim como são para organizar o estado de entrada, e as zombarias pertencem a a seção assert como são para reivindicar resultados contra.
Os manequins não fazem nada. Eles são apenas para preencher listas de parâmetros, para que você não obtenha erros indefinidos ou nulos. Eles também existem para satisfazer o verificador de tipos em idiomas estritamente digitados, para que você possa compilar e executar.
fonte
Stub, Fakes e Mocks têm significados diferentes em diferentes fontes. Sugiro que você apresente os termos internos de sua equipe e concorde com o significado deles.
Eu acho que é importante distinguir entre duas abordagens: - validação de comportamento (implica substituição de comportamento) - validação de estado final (implica emulação de comportamento)
Considere o envio de e-mail em caso de erro. Ao fazer a validação comportamento - você verificar que o método
Send
deIEmailSender
foi executado uma vez. E você precisa emular o resultado do retorno desse método, retornar o ID da mensagem enviada. Então você diz: "Espero queSend
isso seja chamado. E retornarei apenas uma identificação fictícia (ou aleatória) para qualquer chamada" . Esta é a validação de comportamento:emailSender.Expect(es=>es.Send(anyThing)).Return((subject,body) => "dummyId")
Ao fazer a validação de estado, você precisará criar
TestEmailSender
esses implementosIEmailSender
. E implemente oSend
método - salvando a entrada em alguma estrutura de dados que será usada para verificação de estado futuro, como a matriz de alguns objetos,SentEmails
e depois testa você verificará seSentEmails
contém o email esperado. Esta é a validação de estado:Assert.AreEqual(1, emailSender.SentEmails.Count)
Pelas minhas leituras, entendi que a validação de comportamento geralmente se chama Mocks . E validação de estado geralmente chamada Stubs ou Fakes .
fonte
stub e fake são objetos em que eles podem variar sua resposta com base nos parâmetros de entrada. a principal diferença entre eles é que um Fake está mais próximo de uma implementação no mundo real do que um esboço. Os stubs contêm respostas basicamente codificadas para uma solicitação esperada. Vamos ver um exemplo:
Um mock é um passo em frente a falsificações e stubs. As zombarias fornecem a mesma funcionalidade que os stubs, mas são mais complexas. Eles podem ter regras definidas para eles que determinam em que ordem os métodos em sua API devem ser chamados. A maioria das zombarias pode rastrear quantas vezes um método foi chamado e pode reagir com base nessas informações. As zombarias geralmente conhecem o contexto de cada chamada e podem reagir de maneira diferente em diferentes situações. Por isso, as zombarias exigem algum conhecimento da classe que estão zombando. um stub geralmente não pode rastrear quantas vezes um método foi chamado ou em que ordem uma sequência de métodos foi chamada. Um mock se parece com:
fonte
fake object
é uma implementação real da interface (protocolo) ou uma extensão usando herança ou outras abordagens que podem ser usadas para criar - é dependência. Geralmente é criado pelo desenvolvedor como uma solução mais simples para substituir alguma dependênciastub object
é um objeto nua (0, nil e métodos sem lógica) com e extra e pré-definidos (por desenvolvedor) do estado para definir valores devolvidos. Geralmente é criado por frameworkmock object
é muito semelhante,stub object
mas o estado extra é alterado durante a execução do programa para verificar se algo aconteceu (o método foi chamado).fonte