Começando com JMock

13 respostas
Andre_Fonseca

oi,

Estou usando JUnit4 + JMock, criei meu primeiro teste case parecido com isso

@Test
public void testMetodoDAO() throws MinhaException {
  meuDao = context.mock(MeuDAO.class);
  Map<String, String> fakeList = new HashMap<String, String>();
  fakeList.put("1","UM");
  fakeList.put("2","DOIS");
  fakeList.put("3","TRES");

}

como eu faço para testar fakeList com o retorno do metodo dao.getLista(parametro)?

vi que tem uma forma de fazer isso usando assertThat mas não estou sabendo como usar

alguém pode me dar umas dicas??

Tks

13 Respostas

Andre_Fonseca

oi,

será que alguém pode me ajudar com este teste??

Felagund

não conheço o JMock, mas se vc usar o mockito ficaria mais ou menos assim

MeuDao meuDao = mock(MeuDao.class);
when(meuDao.getLista(any(Object.class))).thenReturn(fakeList);

Quando vc usa um mock vc tem que simular o processamento desse metodo, tudo se torna ficticio, acredito que se vc quer testar o retorno de um DAO, não seja a maneira correta de fazer isso, até por que uma busca no BD dificilmente terá o mesmo efeito.

vc pode fornecer mais informações sobre seu teste?

Andre_Fonseca

oi,

eu tenho um método de um dao que retorna um HashMap, eu quero testar o retorno dele, não sei se preciso criar uma lista fake e pegar o retorno da chamada do DAO e comparar… talvez eu precise apenas testar o número de registros esperados e não o retorno ??

achei o exemplo abaixo

context.checking(new Expectations() {{ exactly(2).of(mockObject).iterator(); will(returnIterator(strings)); }}

http://i-proving.ca/space/Mike+Wilkes/blog/2009-06-24_1?showComments=true

Felagund

cara depende muito, esse seu map terá sempre o mesmo retorno para uma entra x?

uma classe pode ser testada (me corrigam se estiver errado) somente se o metodo Y com uma entrada X retorne Z e Z seja o que eu espero

no caso tempos

public Z Y(X);

digamos que Z seja o sobrenome, e X o nome, nossa função Y retorna o sobrenome de uma pessoa nesse caso para o meu nome “Rafael Felix” teria que retornar Felix passando rafael

Nome nome = new Nome("Rafael Felix");
assertEquals("Felix", nome.getSobrenome("Rafael"));

ou

Nome nome = new Nome("Rafael Felix");
assertEquals("Felix", nome.getSobrenome());

Essa é a essencia de um teste, vc tem que ter uma entrada definida e um retorno esperado para tal, se seu map vai retornar sempre com 3 elementos por exemplo ele pode ser testado, mas somente seu tamanho não seu conteudo, o que ao meu ver é um teste bem fraco.

Andre_Fonseca

oi,

o método do DAO retorna um HashMap que pode ser variável dependendo do parâmetro que no caso é apenas um Float

usando Junit eu sempre usei a sintaxe testando se a lista tem o mesmo tamanho e também comparando o conteúdo, algo como

na verdade a minha dúvida é com relação à sintaxe do Jmock

também tenho dúvidas se seria necessário fazer o teste da forma como falei acima

abs

Andre_Fonseca

oi,

agora eu consegui fazer o seguinte

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
Map<String, String> daoList = mockDAO.buscaList(valor);
assertThat(daoList.size(), is(4));

mas estou tendo uma exception

unexpected invocation: mockDAO.buscaList(<2.0F>)
no expectations specified: did you...
 - forget to start an expectation with a cardinality clause?
 - call a mocked method to specify the parameter of an expectation?
what happened before this: nothing!
	at org.jmock.internal.InvocationDispatcher.dispatch(InvocationDispatcher.java:56)

Fiz a declaração dos objetos em

public void setUp() throws Exception {
  context = new Mockery() {{
    setImposteriser(ClassImposteriser.INSTANCE);
  }};
  mockDAO=context.mock(ClasseDAO.class);
}

estou usando JUnit4 e JMock 2.5.1

abs

Andre_Fonseca

oi,

importei o jar que faz a integração entre o JMock e o JUnit jmock-junit4-2.5.1.jar para o classpath do projeto

tb anotei a classe com @RunWith(JMock.class)

o erro está acontecendo já qdo eu tento retornar a lista do mockDAO

alguém pode me dar uma ajuda, esse erro é bem genérico e não ajuda muita coisa.

abs

Felagund

André, vc não deve criar um Mock da classe sendo testada, os mocks são para outras classes auxiliares.
Por exemplo se o objeto meuDao retorna um objeto do tipo MeuObjeto e vc quer comparar o campo nome de MeuObjeto retornado.
ai vc faz um Mock de MeuObjeto com o getNome retornando o esperado.

meuDao vai manter seu processamento normal.

Andre_Fonseca

Felagund:
André, vc não deve criar um Mock da classe sendo testada, os mocks são para outras classes auxiliares.
Por exemplo se o objeto meuDao retorna um objeto do tipo MeuObjeto e vc quer comparar o campo nome de MeuObjeto retornado.
ai vc faz um Mock de MeuObjeto com o getNome retornando o esperado.

meuDao vai manter seu processamento normal.

oi,

desculpe, não entendi direito
quer dizer que eu tenho que mockar a classe DAO e tb o retorno da chamada do método?

tks

Felagund

André Fonseca:
Felagund:
André, vc não deve criar um Mock da classe sendo testada, os mocks são para outras classes auxiliares.
Por exemplo se o objeto meuDao retorna um objeto do tipo MeuObjeto e vc quer comparar o campo nome de MeuObjeto retornado.
ai vc faz um Mock de MeuObjeto com o getNome retornando o esperado.

meuDao vai manter seu processamento normal.

oi,

desculpe, não entendi direito
quer dizer que eu tenho que mockar a classe DAO e tb o retorno da chamada do método?

tks

Seguinte André, vc tem que mockar somente outros objetos, me parece que vc quer testar o retorno do meuDao.
Se é o retorno do metodo X de meuDao que vc quer testar, vc não pode fazer o mock de meuDao, a instancia de meuDao deve ser verdadeira, somente desse modo vc consegue testar.

Quando vc cria um mock, vc tem que dizer o retorno de cada metodo para conseguir testar.

Y

Sim, se voce quer testar o meuDAO nao faz sentido fazer um mock dele, pois voce estaria testando o mock e nao ele.

Supomos que voce tenha uma classe ServiceVenda no metodo processarVenda(), dentro desse metodo voce vai verificar se o cliente tem saldo disponivel para a compra. Para isso voce vai ter que ir ate o banco de dados e buscar as informacoes da conta do cliente, utilizando um clienteDAO, ou qqr coisa assim, é esse clienteDAO que o ServiceVenda vai utilizar que voce vai ter que mockar.

Mockery context = new Mockery();

    final ClienteDAO clienteDao = context.mock(ClienteDAO.class)

    ServiceVenda serviceVenda = new ServiceVenda(dao);

    final Cliente clienteComSaldoInsuficiente = _fakeUmClienteComSaldoInsuficiente();

   context.checking(new Expectations() {{
        oneOf (clienteDao).buscarCliente(umCodigo);
        will(returnValue(clienteComSaldoInsuficiente);
   }});

   //aqui voce vai testar
    serviceVenda.processarVenda();

}

Nesse caso voce diz que ao executar o metodo processarVenda(), o metodo buscarCliente do clienteDAO sera invocado uma vez (oneOf) e vai retornar will(returnValue) o objeto clienteComSaldoInsuficiente, depois dentro do metodo processarVenda voce pode usar o clienteComSaldoInsuficiente para testar o resto do metodo.

Andre_Fonseca

hmm, acho que entendi…

como eu não conheço muito de mocks - ainda preciso ler aquele artigo do Fowler :slight_smile: - eu achei que a utilidade dos objetos mocados era resolver qualquer tipo de dependência externa

pelo exemplo que você colocou fica claro que a finalidade do TestCase é testar o método de negócio e não o DAO, ou seja, se eu tiver uma estrutura de objetos parecida com esta abaixo

[list]TestCase[/list]
[list]Business - objeto real sendo testado[/list]
[list]Facade - mockar[/list]
[list]DAO - mockar[/list]

eu só irei mockar aquilo que foge do objetivo do teste, correto isso??

vlw pela ajuda :slight_smile:

Y

André Fonseca:
hmm, acho que entendi…

como eu não conheço muito de mocks - ainda preciso ler aquele artigo do Fowler :slight_smile: - eu achei que a utilidade dos objetos mocados era resolver qualquer tipo de dependência externa

pelo exemplo que você colocou fica claro que a finalidade do TestCase é testar o método de negócio e não o DAO, ou seja, se eu tiver uma estrutura de objetos parecida com esta abaixo

[list]TestCase[/list]
[list]Business - objeto real sendo testado[/list]
[list]Facade - mockar[/list]
[list]DAO - mockar[/list]

eu só irei mockar aquilo que foge do objetivo do teste, correto isso??

vlw pela ajuda :)

Isso mesmo. Voce aumentaria muito o custo dos testes se tivesse que acessar o banco de dados toda vez que fosse testar seu metodo, e aumentaria sem necessidade porque o que voce esta testando não é o acesso ao banco. Nesses casos voce usa o mock.

Criado 9 de fevereiro de 2010
Ultima resposta 13 de fev. de 2010
Respostas 13
Participantes 3