2010-07-19 7 views
6

Estoy tratando de escribir una prueba JUnit para un proyecto de Spring Roo. Si mi prueba requiere el uso de las clases de entidad, tengo la siguiente excepción:¿Cómo usar las pruebas JUnit con Spring Roo? (Problemas con EntityManager)

java.lang.IllegalStateException: Entity manager has not been injected 
(is the Spring Aspects JAR configured as an AJC/AJDT aspects library?) 

El JAR Aspectos de la primavera parece estar configurado correctamente. En particular, tengo el siguiente en el archivo pom.xml:

<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-aspects</artifactId> 
    <version>${spring.version}</version> 
</dependency> 

y

<plugin> 
    <configuration> 
    <outxml>true</outxml> 
    <aspectLibraries> 
    <aspectLibrary> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-aspects</artifactId> 
    </aspectLibrary> 
    </aspectLibraries> 
    <source>1.6</source> 
    <target>1.6</target> 
    </configuration> 
</plugin> 

y las clases que utilizan las clases de entidad funcionar bien, cuando no se llama a partir de una prueba unitaria. ¿Alguna idea de cómo puedo configurar las cosas para que el administrador de la entidad se inyecte desde una prueba JUnit?

Aquí es mi clase de prueba (más o menos):

public class ServiceExampleTest { 

    @Test 
    public void testFoo() { 
    FooService fs = new FooServiceImpl(); 
    Set<Foo> foos = fs.getFoos(); 
    } 
} 

Esto es suficiente para iniciar la excepción. La clase FooServiceImpl devuelve un conjunto de Foo, donde Foo es una clase de entidad. El método getFoos() funciona cuando la aplicación se ejecuta de la forma habitual. El problema solo viene en el contexto de pruebas unitarias.

+0

Podría publicar su clase de prueba así? Nunca utilicé Spring Roo, pero con las pruebas normales de Spring normalmente tendrías que extender AbstractSpringJUnit4Test (o algo así) o utilizar un Spring Runner personalizado mediante anotaciones para las pruebas. – ponzao

Respuesta

3

Este es un problema increíblemente molesto con Spring Roo y no he resuelto la solución oficial para.

... Pero aquí hay dos soluciones:

  • copiar la primavera-aspectos frasco para su proyecto y luego añadirlo a su aspecto Ruta Proyectos AspectJ
  • Uso Maven para ejecutar las pruebas unitarias (y la señorita la barra verde :()

para la opción de un solo clic derecho en su proyecto seleccione Propiedades-> AspectJ Construir -.> Ruta Aspecto Tab

+0

Aceptaré esta respuesta, pero no estoy en condiciones de verificarla fácilmente, ya que ya no utilizo Roo. (Estoy en un trabajo diferente.) –

+0

@FarmBoy No puedes decir eso sin decir lo que estás usando ahora :) –

+0

Groovy/Grails. Lo amo. –

6

ponzao es correcto que soy capaz de hacerlo. Tengo toda la magia de inyección de primavera haciendo que mi clase de prueba extienda AbstractJunit4SpringContextTests.

p. Ej.

@ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" }) 
public class SelfRegistrationTest extends AbstractJUnit4SpringContextTests { 
+0

Parece desagradable, pero parece funcionar para mí. – kipz

1

La clase de prueba de su unidad debe tener la anotación @MockStaticEntityMethods.

0

También me encontré con la misma excepción y todo se configuró correctamente. Eliminé el proyecto y volví a importarlo en STS (SpringSource Tool Suite) y este problema desapareció.

No estoy seguro de por qué esto lo solucionó, pero este problema podría haber sido causado por el uso de Eclipse para administrar el proyecto generado por Roo antes de cambiar a STS en mi caso.

3

La clase de prueba de la unidad debe tener la anotación @MockStaticEntityMethods.

Solo quería agregar más detalles a la respuesta anterior por @migue, ya que me tomó un tiempo encontrar la manera de hacerlo funcionar. El sitio http://java.dzone.com/articles/mock-static-methods-using-spring-aspects realmente me ayudó a derivar la respuesta a continuación.

Esto es lo que hice para inyectar el administrador de entidades a través de la clase de prueba. Primero anote su clase de prueba con @MockStaticEntityMethods y cree la clase MockEntityManager (que es una clase que simplemente implementa la interfaz EntityManager).

entonces usted puede hacer lo siguiente en su clase de prueba ServiceExampleTest:

@Test 
public void testFoo() { 
    // call the static method that gets called by the method being tested in order to 
    // "record" it and then set the expected response when it is replayed during the test 
    Foo.entityManager(); 
    MockEntityManager expectedEntityManager = new MockEntityManager() { 
    // TODO override what method you need to return whatever object you test needs 
    }; 
    AnnotationDrivenStaticEntityMockingControl.expectReturn(expectedEntityManager); 

    FooService fs = new FooServiceImpl(); 
    Set<Foo> foos = fs.getFoos(); 
} 

Esto significa que cuando usted llama fs.getFoos() la AnnotationDrivenStaticEntityMockingControl habrá inyectado el gestor de la entidad simulacro como Foo.entityManager() es una método estático

También tenga en cuenta que if fs.getFoos() llama a otros métodos estáticos en clases de entidades como Foo y Bar, también se deben especificar como parte de este caso de prueba.

Digamos por ejemplo que Foo tenía un método de búsqueda estático llamado "getAllBars (Long fooId)" que se llama cuando se llama fs.getFoos(), entonces tendría que hacer lo siguiente para hacer que AnnotationDrivenStaticEntityMockingControl funcione.

@Test 
public void testFoo() { 
    // call the static method that gets called by the method being tested in order to 
    // "record" it and then set the expected response when it is replayed during the test 
    Foo.entityManager(); 
    MockEntityManager expectedEntityManager = new MockEntityManager() { 
    // TODO override what method you need to return whatever object you test needs 
    }; 
    AnnotationDrivenStaticEntityMockingControl.expectReturn(expectedEntityManager); 

    // call the static method that gets called by the method being tested in order to 
    // "record" it and then set the expected response when it is replayed during the test 
    Long fooId = 1L; 
    Foo.findAllBars(fooId); 
    List<Bars> expectedBars = new ArrayList<Bar>(); 
    expectedBars.add(new Bar(1)); 
    expectedBars.add(new Bar(2)); 
    AnnotationDrivenStaticEntityMockingControl.expectReturn(expectedBars); 

    FooService fs = new FooServiceImpl(); 
    Set<Foo> foos = fs.getFoos(); 
} 

Recuerde el AnnotationDrivenStaticEntityMockingControl debe estar en el mismo orden que fs.getFoos() llama a sus métodos estáticos.

0

largo tiempo después de la pregunta, pero tengo una solución de trabajo al intentar ejecutar pruebas unitarias Spring Roo desde dentro de Eclipse ...

  1. Hacer que el proyecto abierto en Eclipse
  2. En Eclipse, Proyecto> Limpio > Reconstruir (automático o manual no importa)
  3. una vez que la re-construcción es completa, en una ventana de la consola, tiene limpia y re-paquete (se requiere limpio) Maven:

    mvn clean package

o si las pruebas unitarias están fallando en experto (y lo que necesita Eclipse para depurar sus pruebas)

mvn clean package -Dmaven.test.skip=true 

4. Una vez que el paquete es exitoso, entonces, refrescar volver en Eclipse.

Ahora debería poder ejecutar las pruebas unitarias nuevamente en Eclipse. Encontré que las entidades de edición causaban la mayor frecuencia del error del administrador de entidades. Cuando me quedé sin editarlos, pude editar otras clases y las pruebas unitarias continuarían ejecutándose con éxito.

0

Esto funcionó para mí con Spring Roo:

import static org.junit.Assert.assertEquals; 

import org.junit.Test; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; 

import com.jitter.finance.analyzer.domain.Address; 

@ContextConfiguration(locations = { "classpath*:/META-INF/spring/applicationContext*.xml"}) 
public class EmTest extends AbstractJUnit4SpringContextTests { 

    @Test 
    public void checkEm(){ 
     Address a = new Address(); 
     a.setName("Primo"); 
     a.persist(); 

     Address b = new Address(); 
     b.setName("Secondo"); 
     b.persist(); 

     for(Address ad : Address.findAllAddresses()){ 
      System.out.println(ad.getName()); 
      assertEquals(ad.getName().charAt(ad.getName().length()-1), 'o'); 
     } 
    } 
} 

Con El tipo de dirección como esta:

import org.springframework.roo.addon.javabean.annotations.RooJavaBean; 
import org.springframework.roo.addon.javabean.annotations.RooToString; 
import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; 

@RooJavaBean 
@RooToString 
@RooJpaActiveRecord 
public class Address { 
    private String name; 
} 
Cuestiones relacionadas