Zombando vs. Espionando em estruturas de zombaria

131

Em estruturas de zombaria, você pode zombar de um objeto ou espioná -lo. Qual é a diferença entre os dois e quando devo / devo usar um sobre o outro?

Olhando para Mockito , por exemplo, vejo coisas semelhantes sendo feitas usando espiões e zombarias , mas não tenho certeza quanto à distinção entre os dois.

Vivin Paliath
fonte

Respostas:

157

O objeto simulado substitui completamente a classe simulada, retornando valores registrados ou padrão. Você pode criar uma simulação do "nada". É o que é usado principalmente durante o teste de unidade.

Ao espionar, você pega um objeto existente e "substitui" apenas alguns métodos. Isso é útil quando você tem uma classe enorme e deseja apenas zombar de certos métodos (zombaria parcial). Deixe-me citar a documentação do Mockito :

Você pode criar espiões de objetos reais. Quando você usa o espião, os métodos reais são chamados (a menos que um método tenha sido stubbed).

Espiões de verdade devem ser usados ​​com cuidado e ocasionalmente , por exemplo, ao lidar com código legado.

Em caso de dúvida, use zombaria.

Tomasz Nurkiewicz
fonte
1
Obrigado! Isso torna muito mais claro. Então simulações não delegar ao objeto real que está sendo ridicularizado sempre , mas espiões fazer.
Vivin Paliath
7
As zombarias não têm um "objeto real" - a simulação é criada ab initio.
Carl Manaster 10/10
4
Alguma explicação para o porquê de Mockito alertar contra o uso de espiões o tempo todo? Vejo que eles dizem favorecer a zombaria, mas não sei ao certo o motivo.
Matt
9
Não tenho certeza, mas talvez porque sejam "Mockito" e não "Spyito": D
typoerrpr 25/01/18
16

Mockito alerta que zombaria parcial não é uma boa prática e você deve revisar sua arquitetura Orientada a Objetos. Spy (ou zombaria parcial) é recomendado para testar o código legado .

Suelmar Zanetti
fonte
16

Vou tentar explicar usando um exemplo aqui:

// Difference between mocking, stubbing and spying
@Test
public void differenceBetweenMockingSpyingAndStubbing() {
    List list = new ArrayList();
    list.add("abc");
    assertEquals(1, list.size());

    List mockedList = spy(list);
    when(mockedList.size()).thenReturn(10);
    assertEquals(10, mockedList.size());
}

Aqui, tínhamos um objeto real inicial list, no qual adicionamos um elemento e o tamanho esperado era um.

Nós espionar significado objeto real que pode instruir o método a ser arrancado . Por isso, declaramos que stubbed o método - size()no objeto espião que retornará 10, independentemente do tamanho real.

Em poucas palavras, você espiará objetos reais e apagará alguns dos métodos .

user2775185
fonte
2

Referência: http://javapointers.com/tutorial/difference-between-spy-and-mock-in-mockito/

Ao usar objetos simulados, o comportamento padrão do método quando não stub é não fazer nada. Simples significa que, se for um método nulo, ele não fará nada quando você chamar o método ou se for um método com retorno, poderá retornar nulo, vazio ou o valor padrão.

Enquanto estiver em objetos espiões, é claro, já que é um método real, quando você não estiver stubando o método, ele chamará o comportamento do método real. Se você deseja alterar e zombar do método, é necessário stub-lo.

Jerry C.
fonte
2

Objetos fictícios são passados, mas nunca são realmente usados. Geralmente eles são usados ​​apenas para preencher listas de parâmetros.

Objetos falsos realmente têm implementações de trabalho, mas geralmente usam algum atalho que os torna inadequados para produção (um banco de dados na memória é um bom exemplo).

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.

Espiões são stubs que também registram algumas informações com base em como foram chamadas. Uma forma disso pode ser um serviço de email que registra 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.

Zombarias não são tocos por Martin Fowler

Mohsen
fonte
1

Espiões têm duas definições. Um é onde o método real é chamado, outro onde, nenhuma funcionalidade é chamada e somente valores nulos ou nulos equivalentes são retornados, mas os métodos foram chamados e seu estado foi registrado, geralmente como o método x foi chamado y vezes.

John Heilman
fonte
0

No Mockito, se você atribuir qualquer objeto à variável de instância do Mock Object, isso não afetará o Mock Object.

Porém, no caso do Spy, se você atribuir qualquer objeto à variável de instância Spy Object, o Spy Object será afetado por causa do Spy agir como uma modificação do objeto em tempo real.

Para um exemplo de referência são

@RunWith(MockitoJUnitRunner.class)
public class MockSpyExampleTest {

    @Mock
    private List<String> mockList;

    @Spy
    private List<String> spyList = new ArrayList();

    @Test
    public void testMockList() {
        //by default, calling the methods of mock object will do nothing
        mockList.add("test");
        assertNull(mockList.get(0));
    }

    @Test
    public void testSpyList() {
        //spy object will call the real method when not stub
        spyList.add("test");
        assertEquals("test", spyList.get(0));
    }
}
Yasir Shabbir Choudhary
fonte