Ajuda - Injeção de dependencia

Pessoal, desde ontem estou tentando desenvolver testes unitarios. Já postei algumas duvidas, mais devido a difuldade q estou tendo resolvi colocar uma parte do código, para que vocês possam me ajudar se possível.

A questão é: Na aplicação esse metodo que quero testar retorna 50 registros, porém atraves da classe de teste o size é 0.

Alguem poderia analisar meu código e identificar o q estou fazendo errado ou deixando de fazer???

Classe com o metodo a ser testado:

[code]@Stateful(mappedName = “ejb/ClientManager”)
@Name(“clientManager”)
@Local(OrganizationManagerInterface.class)
@Remote(OrganizationManagerInterface.class)
@Scope(ScopeType.CONVERSATION)
public class ClientManager implements OrganizationManagerInterface {


/**

  • EntityManager
    */
    @In
    private EntityManager entityManager;

public List searchAll() {



}

}[/code]

Interface:

[code]public interface OrganizationManagerInterface {

/**
 * Executes search for the Organization Screen
 * @return List Organization
 */
List<Organization> searchAll();	

}[/code]

–class ClientMockFacade:

[code]public class ClientMockFacade {

/**
 * OrganizationManagerInterface
 */
private OrganizationManagerInterface  organizationManagerInterface;

/**
 * @param organizationManagerInterface organizationManagerInterface
 */
public ClientMockFacade(OrganizationManagerInterface organizationManagerInterface) { 
        this.organizationManagerInterface = organizationManagerInterface; 
    } 

/**
 * searchAll
 * @return true
 */
boolean searchAll() {
	this.organizationManagerInterface.searchAll();
	return true;		
}

}[/code]

–classe de teste:

[code]public class ClientMockTest extends TestCase {

private ClientMockFacade facade; 

private OrganizationManagerInterface mockito; 	

@BeforeClass 
public void setUp() throws Exception { 
    this.mockito = Mockito.mock(OrganizationManagerInterface.class); 
    this.facade = new ClientMockFacade(mockito); 
} 


@AfterClass 
public void TearDown() throws Exception { 
	
} 


@Test 
public final void testSearch() throws Exception {  
    Assert.assertTrue(facade.searchAll());
} 

}[/code]

Desde já agredeço!

Eu utilizo o EasyMock para os meus Mocks mais creio que você tem que passar para o seu mokito o que ele irá retornar, o mock não tem estado nenhum simplesmente só vai retornar o que vc falar para ele retornar…

Exemplo com EasyMock

 private OrganizationManagerInterface mockito;
@Before
public void setUp(){
 this.mockito = createMocK(OrganizationManagerInterface.class);

}

@Test 
public void teste(){
List listaDeResultadosMock = new ArrayList(2);
listaDeResultadosMock.add("meu resultado 1");
listaDeResultadosMock.add("meu resultado 2");
expect(mockito.searchAll()).andReturn(listaDeResultadosMock );
//a linha acima eu estou dizendo ao mock para retornar está lista quando o metodo searchAll() for invocado
replay(mockito);

if(facade.searchAll()==false)
 fail("retorno false")
//Quando testar virá 2 resultados.. pois vc disse ao mock o que retornar..
}

O que está faltando é vc dizer o que o mock ira retornar… eu acho q é isso pelo q entendi.

Valeu Priuli. Obrigada pela dica!

Olá Priuli!

Alterei meu código e estou usando o EasyMock. Mesmo assim o retorno dá minha busca é sempre 0 quando deveria retornar 50.

Se possível vc pode dá uma olhadinha no código abaixo:

[code]public class ClientManagerTest {

/** 
 * ClientManager 	
 */
private ClientManager clientManager;	

/** 
 * OrganizationManagerInterface
 */
private OrganizationManagerInterface mock;	

/**
 * List of organization
 */
private List<Organization> organizationList = new ArrayList<Organization>();

/**
 * setUp
 * @throws Exception Exception
 */
@Before
public void setUp() throws Exception {		
	this.setClientManager(new ClientManager());		
	this.mock = createStrictMock(OrganizationManagerInterface.class);  
}

/**
 * testSearchAll
 */
@Test
public void testSearchAll() {	
	expect(this.mock.searchAll()).andReturn(organizationList);		
	replay(this.mock);
		
	if (this.mock.searchAll().size() == 0) {
		fail("retorno false");
	} 		
}		

}[/code]

Grata!

Izaura, fiz o teste aqui e funcionou … o que está faltando para a lista ser diferente de zero é vc adicionar os objetos nesta lista: ‘organizationList’ …

Olha como eu testei…

package junitteste;

import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;
import org.junit.Before;
import org.junit.Test;

public class ClientManagerTest {   
            
    private OrganizationManagerInterface mock;  
    
    private List<Organization> organizationList =new ArrayList<Organization>();   
     
    @Before   
    public void setUp() throws Exception {           
        this.mock = createStrictMock(OrganizationManagerInterface.class);
        for(int i = 0 ; i < 50 ; i++)
             organizationList.add(new Organization());

    }   
       
    @Test   
    public void testSearchAll() {     
        expect(this.mock.searchAll()).andReturn(organizationList);         
        replay(this.mock);   
        
        List<Organization> resultado = this.mock.searchAll();
        if (resultado.size() == 0) {   
            fail("retorno false");   
        }     
        if(!resultado.equals(organizationList))
        	fail("não é a lista que eu pedi para o mock retornar");
        System.out.println("Quantidade é:"+resultado.size(); //irá imprimir no console o valor de 50
    }         
       
} 

Eu usei o junit4 + EasyMock, e funciono perfeitamente a quantidade de registros na lista será 50 do método this.mock.searchAll()
e a lista de retorno será a mesma lista da linha 26 …

*lembrando que o seu DAO/EntityManager não deve ser chamado em hipotese alguma no teste de unidade, um teste de unidade apenas testa classe por classe, e não mais de uma classe por teste e esta classe a ser testada não pode ter chamadas de io, dao, ou outras classes de negocio, pois ai se trataria de teste de integração…

Olá Priuli! Mais uma vez obrigada pela disposição em ajudar.

Irei tentar conforme sua solução. Mais confesso que ainda não entendi como conseguiu que esses dados tenham vindo do BD.

Não querendo ser chata (rs), mais andei lendo algumas matérias e muitas “falavam” sobre o Spring, DbUnit … desculpe a ignorancia mais em sistemas desenvolvidos para Web utilizando EJB, SEAM, HIBERNATE, JSF … se usa o Spring e/ou DbUnit?

Izaura

O DbUnit é usando para testar a parte dao do seu sistema e pode sim ser utilizado em projetos com ejb, jsf… porem o hibernate já tem seu teste feito pelos desenvolvedores e não sei se é possivel fazer teste do hibernate com o DbUnit…

O Spring e EJB são frameworks poderosos para aplicações cooporativas para controle de transação, custurização, e muitas outras coisas para facilitar a nossa vida, a diferença é que o Spring é mais leve e não utilizado para sistemas distribuidos já o EJB é utilizado para sistemas distribuidos, ou usa 1 ou outro mais os dois juntos na mesma aplicação ñ…
Mas tanto aplicações web ou desktop podem usar sim o Spring ou DBUnit. este temaa é bem amplo mais vale a pena estudar…

Valeu pela explicação.

Voltando ao meu problema, no seu exemplo esse valor de 50 esta sendo “forçado”, eu preciso realmente conseguir chegar até o banco de dados.

Preciso descobrir como faço essa DI da Entity Manager.

Obriagada!

Izaura,

Como Priuli disse, o seu teste retornou size = 0 porque você não adicionou nenhuma informação na sua lista, assim o seu MOCK irá retornar a lista que você colocou nele, ou seja, uma lista vazia. O mock é um objeto “falso” onde você sabe exatamente o estado e comportamento dele, assim se você passar para ele Abacaxi ele irá retornar abacaxi, se passar banana vai retornar banana e assim por diante. Ele não vai executar o que o seu código real faz, que no seu caso creio que seja ir no banco de dados buscar as informações.

A nível de teste unitário esse seu teste NÃO deve ir buscar informações do banco, pois o banco é um recurso externo e o teste unitário visa testar apenas a menor unidade do código (o método). Tudo o que for externo deve ser mockados (isso serve também para outras classes e interfaces).

Claro que você poderia fazer um teste específico para testar a sua classe de persistência com o banco de dados, mas nesse caso o ideal é você conhecer o estado inicial das informações no banco de dados (eu geralmente uso o HSQLDB em memória para isso, fazendo um drop e criando as tabelas a cada testes, garantindo o seu estado inicial), porém esses são casos mais raros de acontecer, geralmente em uma consulta um pouco mais elaborada. Aqui o DBUnit pode te ajudar a preparar a massa de dados.

Acredito que falta você entender um pouco melhor o conceito de teste unitário (testar a menor unidade do sistema) e mock. Certamente isso é algo que agrega muito no sistema e hoje em dia eu não vejo um sistema sem Unit Testing.

Espero ter ajudado

Olá Jair!

Se eu entendi direito, o acesso ao BD não irei conseguir, tenho que “simular” os dados do banco manualmente

Supondo que na tabela tenha os seguinted dados:

cod nome descricao
1 abacaxi emagrece
2 caqui engorda
3 tomate molho

Tenho q add na lista, para aí sim executar o teste???

Só confirmando, acesso ao banco atraves de mock para realizar os teste diretamente do BD é totalmente errado? - preciso argumentar isso aqui na empresa - rs

Obrigada!

Isso, um teste de unidade nao deve conectar ao banco e tb ñ deve criar arquivos em disco nem nada que seja de escopo de outra classe.

O nome já diz… Teste Unitario - Unico
mais não existe apenas o Teste Unitario existem outros tb mais o TesteUnitario que define a qualidade do seu sistema e deve ser usado no projeto todo para aumentar o nivel de qualidade do seu proj…

[quote=Jair Rillo Junior]Izaura,

Como Priuli disse, o seu teste retornou size = 0 porque você não adicionou nenhuma informação na sua lista, assim o seu MOCK irá retornar a lista que você colocou nele, ou seja, uma lista vazia. O mock é um objeto “falso” onde você sabe exatamente o estado e comportamento dele, assim se você passar para ele Abacaxi ele irá retornar abacaxi, se passar banana vai retornar banana e assim por diante. Ele não vai executar o que o seu código real faz, que no seu caso creio que seja ir no banco de dados buscar as informações.

A nível de teste unitário esse seu teste NÃO deve ir buscar informações do banco, pois o banco é um recurso externo e o teste unitário visa testar apenas a menor unidade do código (o método). Tudo o que for externo deve ser mockados (isso serve também para outras classes e interfaces).

Claro que você poderia fazer um teste específico para testar a sua classe de persistência com o banco de dados, mas nesse caso o ideal é você conhecer o estado inicial das informações no banco de dados (eu geralmente uso o HSQLDB em memória para isso, fazendo um drop e criando as tabelas a cada testes, garantindo o seu estado inicial), porém esses são casos mais raros de acontecer, geralmente em uma consulta um pouco mais elaborada. Aqui o DBUnit pode te ajudar a preparar a massa de dados.

Acredito que falta você entender um pouco melhor o conceito de teste unitário (testar a menor unidade do sistema) e mock. Certamente isso é algo que agrega muito no sistema e hoje em dia eu não vejo um sistema sem Unit Testing.

Espero ter ajudado[/quote]

Olá Jair,

Mais uma vez quero agradecer a você e ao pessoal pela sua disposição em me ajudar.
Jair, eu até entendi a solução que você está propondo, porém gostaria de saber como eu poderia testar o método searchAll() do ClientManager (que é um EJB), sendo que o método searchAll depende do entityManager que é injetado pelo JBoss Seam.

Obrigada