Mock

Olá… estou tentando aprender sobre Testes Unitários, porém estou com muitas duvidas, e não consigo achar respostas para estas duvidas. Na realidade já li muita coisa sobre testes unitários e consegui absorver muita coisa, mas não consigo aplicar, este é o grande problema.

Eu tenho uma aplicação e estou querendo aplicar teste unitários nela. Escolhi uma classe para começar a tentar, só que essa minha classe esta integrada com outras classes, foi assim que cheguei no Mock. Pelo que eu estava lendo sobre o Mock, eu tenho que criar interfaces para alguma coisa, e esse é o meu problema, não faço ideia do porque criar interfaces para meu mock, não consigo visualizar como aplicar mocks nos meus testes, se alguem sabe explicar, tem exemplos práticos, alguma coisa que ajude, estou precisando muito.

Obrigado.

Olá yatta!

A grosso modo, você fazer “Mock” de objetos quer dizer que você simulará o comportamento de determinado
objeto.
Imagine que você tenha classes que dependam de outras. É complicado você instanciar todas as classes
que o seu Teste precisa.
O Mock nos ajuda neste momento. Podemos simular o comportamento de dado objeto e continuar com o teste
da funcionalidade em questão, sem nos preocuparmos com outras funcionalidades.

Em relação a criação de interfaces, na verdade no GUJ tem diversas discussões sobre a sua utilização,
mas em relação ao Mock em específico é possível você fazer Mocks de classes concretas.
Se o pessoal não elaborar um exemplo antes, eu posto um exemplo simples.

Abraços!

Neste trecho tu respondeu tua pergunta… tu tem uma classe que envolve outras… mais teu objetivo é testar apenas uma unica classe (teste UNITÁRIO ) ou seja, imagina se para cada classe que tu tiver que testar, tu tenha que preparar todas as classes envolvidas? e se essas classes tem mais mais classes envolvidas? vira uma bola de neve, e teu teste acaba te atrapalhando ao invez de te ajudar.

a moral do mock é mais ou menos isso, abstrair a complexidade de outras entidades envolvidas, ou seja um pensamento mais ou menos assim “não interessa o que essa classe faz, nesse teste ela vai me retornar isso”.
não sei se ajudei ou atrapalhei XD.

Fala Yetta!

Em um exemplo bem simples, temos o seguinte cenário:
Imaginemos que você precisa fazer um teste, onde será mostrada uma mensagem de erro para o usuário,
caso ele deixe os campos de um formulário em branco, como Nome e Endereco

@Test
public void deveriaMostrarMensagemDeCamposEmBrancoCasoOsCamposNomeEEnderecoNaoEstejamPreenchidos() throws Exception {
	final FormularioView view = contexto.mock(FormularioView.class);
	FormularioPresenter presenter = new FormularioPresenter(view, null);
	
	contexto.checking(new Expectations() {{
		allowing(view).getNome(); will(returnValue(""));
		allowing(view).getEndereco(); will(returnValue(""));

		one(view).mensagemDeCamposEmBranco();
	}});
	
	presenter.enviaDadosDoFormulario(NOME_EM_BRANCO, ENDERECO_EM_BRANCO);
}

Neste exemplo, queremos que a mensagem de erro seja mostrada. o código one(view).mensagemDeCamposEmBranco();
indica este método deve ser chamado uma vez quando o presenter.enviaDadosDoFormulario() for invocado.
Assim, não será mostrada uma mensagem na tela, mas sim teremos uma simulação de que essa mensagem será mostrada,
ou seja, garantimos que esse código da mensagem de erro será invocado, caso os campos estejam em branco.

E como indicamos que os campos estão em branco?
Desta forma: allowing(view).getEndereco(); will(returnValue(""));
Neste código indicamos que queremos que a propriedade endereco tenha como valor uma string vazia.
O mesmo para a propriedade nome.

Viu a facilidade?
Simulamos dois campos com string vazia, simulamos a chama a um método da nossa View e não foi preciso Instanciar objeto,
setar valor na mão, etc. “Mockamos” estes objetos e trabalhamos em cima das simulações.
No exemplo, estou usando JMock mas você pode usar outros, como Mockito.

Razoável?

Abraços!

O filipechaves resumiu legal a idéia “abstrair a complexidade de outras entidades envolvidas”.
Assim você não precisará instanciar e trabalhar “na mão” as outras classes que o seu teste depender.

Até mais!

Os primeiros frameworks de mock em java baseavan-se em ProxyClasses p/ implementar o mock. ProxyClasses só funcionam apartir de uma interface (agora ñ me pergunte pq, só sei q é assim). Atualmente a maioria dos frameworks de mock fazem manipulação de bytecode e ñ dependem mais de interfaces. Procure por mockito e a sua duvida estará resolvida.

Muito boa sua explicação e seu exemplo. Estou começando a pegar a ideia.

Agora, quando vou tentar fazer aqui na minha aplicação, não consigo sair do lugar.

Vou postar aqui o método que quero fazer o teste, para ver se você consegue me guiar um pouco.

public boolean salvar(AtendimentoAberto atendimentoAberto) {
        try {
            session.beginTransaction();
            atendimentoAberto.setHoraChegada(new Date());
            atendimentoAberto.setNumero(getProximoNumero());
            atendimentoAberto.getPrioridade();
            atendimentoAberto.getFila().getUnidade().setUltimaSenha(atendimentoAberto.getNumero());
            atendimentoAbertoDAO.salvar(atendimentoAberto);
            session.getTransaction().commit();
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            session.close();
        }
    }

Este método salva no BD os valores passados. Se puder me ajudar eu agradeço muito!!!

Obrigado!!

P.S: Estou usando o Mockito.

po amigo, o que tu queres testar nesta classe?

tenha em mente que o teste nada mais é que uma garantia que o codigo de fato funciona como o esperado.

neste caso tu quer testar os dados que chegaram? ou a persistencia?

Como o amigo filipechaves falou, você poderia definir quais os testes que você pretende fazer.
Se você nunca trabalhou com testes, eu sugiro você fazer testes unitários, testando regras de negócio
específicas.
Se você quer testes com o banco de dados, seus testes acabam sendo Testes de Integração (a grosso modo,
já que Testes de Integração podem ser testes de componentes distintos) e os testes de integração
acabam sendo mais complexos.
Defina mais ou menos o que você deseja testar que o pessoal vai tentando auxiliar.

Abraços!