Wednesday, September 14, 2011

Mock/Stub EntityManager in Spring Roo

Problem

Trying to create unit test to the method persist from a class created in Spring Roo using a stub do the EntityManger that is passed in the constructor as follows:


public class ClassATest {
    @Test
    public void whenPersistShoulCallClassB() throws Exception {
        
        Mockery contexto = new Mockery();
        final ClassB classB = contexto.mock(ClassB.class);
        
        final ClassA classA = 
            new ClassA(getEntityManagerStub(), classB);

        contexto.checking(new Expectations() {{
            one(classB).doSomething(classA);

        }
    });
        classA.persist();
        
        contexto.assertIsSatisfied();
    }

    private EntityManager getEntityManagerStub() {
        return new EntityManager() {
            ...
        }
    }
}
Source from ClassA

public class ClassA {
...

    public ClassA(EntityManager entityManager, ClassB classB) {
        this.entityManager = entityManager;
        this.classB = classB;
    }



    @Transactional
    public void persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
     
        this.entityManager.persist(this);
     
        classB.doSomething(this);
     
    }

...
 }


This test works inside Eclipse, but doesn´t when called by maven, as a result of  mvn jetty:run-exploded.

Reason

Probably Spring Roo is injecting the EntityManager just before the call to the constructor.

Solution

Use of setter injection, as follows:

public class ClassATest {
    @Test
    public void whenPersistShoulCallClassB() throws Exception {
        
        Mockery contexto = new Mockery();
        final ClassB classB = contexto.mock(ClassB.class);
        
        final ClassA classA =
            new ClassA(classB);
        classeA.setEntityManager(getEntityManagerStub());
        
        contexto.checking(new Expectations() {{
            one(classB).doSomething(classeA);

        }
    });
        classeA.persist();
        
        contexto.assertIsSatisfied();
    }

    private EntityManager getEntityManagerStub() {

        return new EntityManager() {
            ...
        }

    }
}


Código da ClasseA


public class ClasseA {
...

    public ClasseA(ClasseB classeB) {
        this.classeB = classeB;
    }


    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }




    @Transactional
    public void persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
      
        this.entityManager.persist(this);
      
        classeB.doSomething(this);
      
    }

...
 }


There must be a more elegant solution that enables the utilization of construction injection. When I have time to research, I will post it.






No comments:

Post a Comment