Pergunta

Eu sei como eu usar esses termos, mas eu estou querendo saber se existe são aceitos definições para falsificação , zombeteiro e stubbing testes de unidade? Como você define estes para seus testes? Descrever situações em que você pode usar cada um.

Aqui está como eu usá-los:

Falso : uma classe que implementa uma interface, mas contém dados fixos e nenhuma lógica. Simplesmente retorna "bom" ou "mau" de dados, dependendo da aplicação.

Mock : uma classe que implementa uma interface e permite que a capacidade de definir dinamicamente os valores para retornar / exceções para jogar a partir de métodos particulares e fornece a capacidade de verificar se os métodos particulares foram chamados / não chamado.

Stub :. Como uma classe falsa, exceto que ele não fornece a capacidade de verificar que os métodos têm sido chamados / não é chamado

Mocks e topos pode ser mão gerado ou gerado por uma plataforma de simulacros. aulas falsos são gerados com a mão. Eu uso simulações principalmente para verificar as interações entre a minha classe e classes dependentes. Eu uso stubs uma vez que eu ter verificado as interações e estou testando caminhos alternativos através do meu código. Eu uso as classes falsos principalmente para dependências de dados abstratos para fora ou quando mocks / stubs são muito tedioso para configurar cada tempo.

Foi útil?

Solução

Você pode obter algumas informações:

Martin Fowler sobre Mock e Stub

Falso objetos realmente tem implementações de trabalho, mas geralmente levar algum atalho que os torna não é adequado para a produção

Stubs fornecer respostas enlatadas para chamadas feitas durante o teste, geralmente não responder a todos para fora tudo o que está programado em para o teste. Stubs também pode registrar informações sobre chamadas, como um rascunho gateway de e-mail que lembra as mensagens que 'enviados', ou talvez apenas quantas mensagens é enviados '.

Mocks são o que nós estamos falando aqui:. Objetos pré-programado com as expectativas que formam uma especificação das chamadas que são esperados para receber

xunitpattern :

Falso : Nós adquirir ou construir uma aplicação muito leve da mesma funcionalidade que fornecido por um componente que o SUT depende e instruir o SUT para usá-lo em vez do real

.

Stub : Esta implementação é configurado para responder aos apelos do SUT com os valores (ou exceções) que exercem o código não testado (ver Erros de Produção na página X) dentro do SUT. Uma indicação chave para usando um topo de teste está a ter código não testado causado pela incapacidade para controlar as entradas indirecta do SUT

Mock objecto que implementa a mesma interface como um objecto no qual a SUT (Under Test System) depende. Podemos usar um objeto fictício como um ponto de observação, quando o que precisamos fazer Comportamento de verificação para evitar ter um Requisito Untested (ver Erros de Produção na página X) causada por uma incapacidade de observar os efeitos colaterais de chamar métodos no SUT.

Pessoalmente

Eu tento simplificar usando: Mock e Stub. Eu uso Mock quando é um objeto que retorna um valor que está definido para a classe testado. Eu uso Stub para imitar uma interface ou classe abstrata para ser testado. Na verdade, isso realmente não importa o que você chamá-lo, eles são todas as classes que não são usados ??na produção, e são utilizados como classes de utilitários para testar.

Outras dicas

Stub - um objeto que fornece respostas para chamadas de método pré-definido.

Mock -. Um objeto no qual você definir expectativas

Falso - um objecto com capacidade limitada (para os fins de ensaio), por exemplo um serviço falso web.

Test Duplo é o termo geral para topos, simulações e falsificações. Mas informalmente, muitas vezes você vai ouvir as pessoas simplesmente chamá-los de simulações.

Estou surpreso que esta questão tem sido em torno de tanto tempo e ninguém tem ainda fornecido uma resposta com base em Roy Osherove de "A Arte da Unidade de Teste" .

Em "3,1 tocos Introduzindo" define um esboço como:

Um esboço é um substituto controlável para uma dependência existente (Ou colaborador) no sistema. Usando um esboço, você pode testar seu código sem lidar com a dependência diretamente.

e define a diferença entre canhotos e zomba como:

A principal coisa a lembrar sobre simulações contra canhotos é que as simulações são como canhotos, mas você invocar contra o objeto de simulação, enquanto você não fazer valer contra um topo.

Falso é apenas o nome usado para ambos os topos e simulações. Por exemplo, quando você não se preocupam com a distinção entre canhotos e simulações.

A forma distingue do Osherove entre canhotos e simulações, significa que qualquer classe usado como uma farsa para testes podem ser tanto um esboço ou uma simulação. Que é para um teste específico depende inteiramente de como você escreve os cheques em seu teste.

  • Quando seus valores teste verifica na classe sob teste, ou na verdade qualquer lugar, mas o falso, o falso foi usado como um topo. Ele apenas valores para a classe fornecido em teste para uso, quer directamente através valores retornados por chamadas sobre ele ou indiretamente através de causar efeitos colaterais (em algum estado), como resultado de chamadas sobre ele.
  • Quando seu teste verifica valores do falso, ele foi usado como um mock.

Exemplo de um teste onde a classe FakeX é usado como um topo:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, cut.SomeProperty);

A instância fake é usado como um esboço, pois o Assert não usa fake em tudo.

Exemplo de um ensaio em que X classe de teste é utilizada como um mock:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, fake.SomeProperty);

Neste caso, os Assert verificações um valor sobre fake, fazendo que um falso simulada.

Agora, é claro estes exemplos são altamente planejado, mas não vejo grande mérito nessa distinção. Isso faz você ciente de como você está testando seu material e onde as dependências do seu teste são.

Eu concordo com o Osherove que

a partir de uma perspectiva de manutenção pura, em meus testes usando simulações cria mais problemas do que não usá-los. Essa tem sido a minha experiência, mas estou sempre aprendendo algo novo.

Afirmando contra o falso é algo que você realmente quer evitar, pois faz seus testes altamente dependente da implementação de uma classe que não é aquele em teste em tudo. O que significa que os testes para ActualClassUnderTest classe pode começar a quebrar porque a implementação de ClassUsedAsMock alterado. E que envia-se um mau cheiro para mim. Os testes de ActualClassUnderTest deve de preferência apenas quebrar quando ActualClassUnderTest é alterado.

Eu percebo que a escrita afirma contra o falso é uma prática comum, especialmente quando você é um tipo mockist de TDD assinante. Eu acho que estou firmemente com Martin Fowler no campo classicista (Veja de Martin Fowler "zomba não sejam Stubs" ) e como Osherove testes de interação evitar (que só pode ser feito por afirmando contra o falso), tanto quanto possível.

Para se divertir lendo sobre por que você deve evitar simulações, tal como definido aqui, no Google por "passarinheiro classicista mockist". Você vai encontrar uma infinidade de opiniões.

Tal como referido pelo mais votados resposta, Martin Fowler discute estas distinções em Mocks não são Stubs , e em particular o subtítulo a diferença entre Mocks e Topos , por isso certifique-se de ler esse artigo.

Ao invés de focar em como estas coisas são diferentes, eu acho que é mais esclarecedor para se concentrar em por estes são conceitos distintos. Cada existe para uma finalidade diferente.

Fakes

A falso é uma implementação que se comporta "naturalmente", mas não é "real". Estes são conceitos difusos e pessoas tão diferentes têm diferentes entendimentos sobre o que torna as coisas um falso.

Um exemplo de um falso é uma base de dados na memória (por exemplo, usando sqlite com a loja :memory:). Você nunca iria usar isso para produção (desde que os dados não é mantido), mas é perfeitamente adequado como um banco de dados para usar em um ambiente de teste. É também muito mais leve do que um banco de dados "real".

Como outro exemplo, talvez você usa algum tipo de armazenamento de objetos (por exemplo, Amazon S3) na produção, mas em um teste que você pode simplesmente salvar objetos para arquivos em disco; então a sua implementação "Salvar em disco" seria uma farsa. (Ou você pode até mesmo simular a "salvar em disco" operação usando um sistema de arquivos em memória em vez disso.)

Como um terceiro exemplo, imagine um objeto que fornece uma API de cache; Um objeto que implementa a interface correta, mas que simplesmente não executa nenhuma cache em todos, mas sempre retorna um erro de cache seria uma espécie de falso.

O propósito de um falso é não a afetar o comportamento do sistema em teste , mas sim para simplificar a implementação do teste (removendo dependências desnecessárias ou pesados).

Stubs

A rascunho é uma implementação que se comporta "não natural". Ele é pré-configurado (geralmente pelo set-up test) para responder às entradas específicas com saídas específicas.

O propósito de um esboço é obter o seu sistema em teste em um estado específico. Por exemplo, se você estiver escrevendo um teste para algum código que interage com uma API REST, você poderia stub fora a API REST com uma API que sempre retorna uma resposta enlatados, ou que responde a uma solicitação da API com um erro específico. Desta forma, você pode escrever testes que fazem afirmações sobre como funciona o sistema para estes Estados; por exemplo, testar a resposta a seus usuários a obter se a API retorna um erro 404.

Um esboço é geralmente aplicada apenas responder às interações exatas que você já contou a responder. Mas a característica chave que faz algo um esboço é a sua finalidade :. Um esboço é tudo sobre a criação de seu caso de teste

Mocks

A simulada é semelhante a um esboço, mas com verificação adicionado. O propósito da maqueta dos cartões é fazer afirmações sobre como seu sistema em teste interagiu com a dependência .

Por exemplo, se você estiver escrevendo um teste para um sistema que envia arquivos para um site, você poderia construir um simulada que aceita um arquivo e que você pode usar para afirmar que o arquivo foi corrigir. Ou, em uma escala menor, é comum o uso de uma simulação de um objeto para verificar se o sistema em teste chama métodos específicos do objeto ridicularizado.

Mocks estão vinculados a testes de interação , que é uma metodologia de teste específico. Pessoas que preferem test estado do sistema em vez de interações do sistema usará simulações com moderação se em tudo.

Test duplos

falsificações, topos, e zomba todos pertencem à categoria de teste de duplas . Um teste duplo é qualquer objeto ou sistema que você usa em um teste em vez de outra coisa. A maioria autoteste de software acoplado envolve o uso de duplas de teste de algum tipo ou de outro. Alguns outros tipos de duplas de teste incluem valores fictícios , espiões , e I / O blackholes .

Para ilustrar o uso de topos e simulações, eu gostaria de também incluir um exemplo baseado em Roy Osherove do " A Arte da Unidade de Teste ".

Imagine que, temos uma aplicação LogAnalyzer que tem a única funcionalidade de registros de impressão. Ele não só precisa falar com um serviço web, mas se o serviço web gera um erro, LogAnalyzer tem que registrar o erro a uma dependência externa diferente, enviá-lo por e-mail para o administrador do serviço web.

Aqui está a lógica gostaríamos de teste dentro LogAnalyzer:

if(fileName.Length<8)
{
 try
  {
    service.LogError("Filename too short:" + fileName);
  }
 catch (Exception e)
  {
    email.SendEmail("a","subject",e.Message);
  }
}

Como você testar se LogAnalyzer chama o serviço de e-mail corretamente quando o serviço web lança uma exceção? Aqui estão as perguntas que estamos confrontados com:

  • Como podemos substituir o serviço web?

  • Como podemos simular uma exceção do serviço de web para que possamos testar a chamada para o serviço de e-mail?

  • Como é que sabemos que o serviço de e-mail foi chamado corretamente ou pelo tudo?

Podemos lidar com as duas primeiras perguntas por usando um esboço para o serviço web . Para resolver o terceiro problema, podemos usar um objeto de simulação para o serviço de e-mail .

A falsificação é um termo genérico que pode ser usado para descrever qualquer um esboço ou uma mock.In nosso teste, teremos duas falsificações. Um deles será o mock serviço de e-mail, que usaremos para verificar se os parâmetros corretos foram enviados para o serviço de e-mail. O outro será um stub que usaremos para simular uma exceção lançada a partir do serviço web. É um esboço, porque não estará usando o falso serviço web para verificar o resultado do teste, apenas para certificar-se as execuções de teste corretamente. O serviço de e-mail é um mock porque nós vamos fazer valer contra ele que ele foi chamado corretamente.

[TestFixture]
public class LogAnalyzer2Tests
{
[Test]
 public void Analyze_WebServiceThrows_SendsEmail()
 {
   StubService stubService = new StubService();
   stubService.ToThrow= new Exception("fake exception");
   MockEmailService mockEmail = new MockEmailService();

   LogAnalyzer2 log = new LogAnalyzer2();
   log.Service = stubService
   log.Email=mockEmail;
   string tooShortFileName="abc.ext";
   log.Analyze(tooShortFileName);

   Assert.AreEqual("a",mockEmail.To); //MOCKING USED
   Assert.AreEqual("fake exception",mockEmail.Body); //MOCKING USED
   Assert.AreEqual("subject",mockEmail.Subject);
 }
}

É uma questão de fazer os testes expressivo. I definir as expectativas em um Mock se eu quiser o teste para descrever a relação entre dois objetos. Eu toco retornar valores se eu sou a criação de um objeto de apoio para me levar ao comportamento interessante no teste.

A única coisa que você afirma sobre ele, é chamado de simulada objeto e tudo o mais que apenas ajudou a execução do teste, é um rascunho .

Se você está familiarizado com Organize-Act-Assert, em seguida, uma forma de explicar a diferença entre stub e zombar de que pode ser útil para você, é que os topos pertencem à seção de organizar, como eles são para organizar estado de entrada e mocks pertencem à seção assert como eles são para afirmar resultados contra.

Dummies não fazer nada. Eles são apenas para encher parâmetro listas, de modo que você não seja indefinida ou erros nulos. Eles também existem para satisfazer o verificador de tipos em linguagens rigorosamente digitadas, para que possa ser autorizado a compilar e executar.

rascunho e falso são objetos em que eles podem variar a sua resposta com base em parâmetros de entrada. a principal diferença entre eles é que a falsificação está mais perto de uma implementação real do que um topo. Topos conter basicamente respostas codificado para um pedido esperado. Vamos ver um exemplo:

public class MyUnitTest {

 @Test
 public void testConcatenate() {
  StubDependency stubDependency = new StubDependency();
  int result = stubDependency.toNumber("one", "two");
  assertEquals("onetwo", result);
 }
}

public class StubDependency() {
 public int toNumber(string param) {
  if (param == “one”) {
   return 1;
  }
  if (param == “two”) {
   return 2;
  }
 }
}

A simulada é um passo para cima a partir de falsificações e canhotos. Simulações fornecer a mesma funcionalidade como canhotos, mas são mais complexos. Eles podem ter regras definidas para eles que ditam no que métodos de ordem na sua API deve ser chamado. A maioria das simulações pode acompanhar quantas vezes um método foi chamado e pode reagir com base nessa informação. Mocks geralmente sabem o contexto de cada chamada e pode reagir de maneira diferente em diferentes situações. Devido a isso, simulações requerem algum conhecimento da classe que eles estão zombando. um topo geralmente não pode acompanhar quantas vezes um método foi chamado ou em que ordem de uma seqüência de métodos foi chamado. Um mock parece com:

public class MockADependency {

 private int ShouldCallTwice;
 private boolean ShouldCallAtEnd;
 private boolean ShouldCallFirst;

 public int StringToInteger(String s) {
  if (s == "abc") {
   return 1;
  }
  if (s == "xyz") {
   return 2;
  }
  return 0;
 }

 public void ShouldCallFirst() {
  if ((ShouldCallTwice > 0) || ShouldCallAtEnd)
   throw new AssertionException("ShouldCallFirst not first thod called");
  ShouldCallFirst = true;
 }

 public int ShouldCallTwice(string s) {
  if (!ShouldCallFirst)
   throw new AssertionException("ShouldCallTwice called before ShouldCallFirst");
  if (ShouldCallAtEnd)
   throw new AssertionException("ShouldCallTwice called after ShouldCallAtEnd");
  if (ShouldCallTwice >= 2)
   throw new AssertionException("ShouldCallTwice called more than twice");
  ShouldCallTwice++;
  return StringToInteger(s);
 }

 public void ShouldCallAtEnd() {
  if (!ShouldCallFirst)
   throw new AssertionException("ShouldCallAtEnd called before ShouldCallFirst");
  if (ShouldCallTwice != 2) throw new AssertionException("ShouldCallTwice not called twice");
  ShouldCallAtEnd = true;
 }

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