Qual a diferença entre 'mock' e 'stub'?

Mock e stub são termos usados no contexto de testes de software para definir diferentes tipos de objetos simulados que substituem componentes reais durante os testes. Embora ambos sejam usados para criar cenários controlados, eles têm propósitos ligeiramente diferentes.

Um stub é um objeto simulado que tem comportamento pré-definido e é usado para “preencher os espaços em branco” no código sendo testado. Geralmente, um stub é usado para fornecer respostas fixas para as chamadas de método ou consulta de propriedades em um objeto real. Por exemplo, imagine que um componente do seu sistema dependa de uma API externa. Para testar esse componente sem depender da API real, você pode criar um stub que retorna uma resposta predefinida, simulando o comportamento esperado da API externa em um determinado cenário. Dessa forma, o stub permite que você teste o comportamento do componente em diferentes situações de forma controlada.

Por outro lado, um mock é um objeto simulado que permite definir expectativas específicas sobre como ele será usado durante os testes. Um mock é usado para simular o comportamento de um objeto real e também para verificar se determinadas chamadas de método ou comportamentos esperados ocorrem durante o teste. Em outras palavras, um mock é mais focado em simular interações entre objetos. Por exemplo, imagine que você tenha um método que envia e-mails em um determinado cenário do seu sistema. Para testar esse método sem enviar e-mails reais, você pode criar um mock do objeto responsável pelo envio de e-mails e definir expectativas sobre quais métodos específicos devem ser chamados (por exemplo, enviarEmail) e com que argumentos. Em seguida, você pode verificar se essas expectativas foram cumpridas durante o teste.

Em resumo, enquanto um stub é usado para fornecer respostas pré-definidas e substituir partes do código real que não são relevantes para o teste, um mock é usado para simular interações entre objetos e verificar se comportamentos específicos ocorreram durante o teste. Ambos são úteis em diferentes cenários de teste e ajudam a isolar o código sob teste de dependências externas.