Começando com JMock

oi,

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

[code]
@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”);

}[/code]

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

oi,

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

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?

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

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.

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

oi,

agora eu consegui fazer o seguinte

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

mas estou tendo uma exception

[code]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)
    [/code]

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

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

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.

[quote=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.[/quote]

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

[quote=André Fonseca][quote=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.[/quote]

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[/quote]

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.

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.

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:

[quote=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 :)[/quote]

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.