2010-07-19 9 views
6

Sto provando a scrivere un test JUnit per un progetto Spring Roo. Se il mio test richiede l'uso delle classi di entità, ottengo la seguente eccezione:Come utilizzare i test JUnit con Spring Roo? (Problemi con EntityManager)

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

aspetti primavera JAR sembra essere configurato correttamente. In particolare, ho il seguente nel file pom.xml:

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

e

<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> 

e le classi che utilizzano le classi di entità funzionare bene, quando non è chiamato da un test JUnit. Qualche idea su come posso impostare le cose in modo che il gestore Entity venga iniettato da un test JUnit?

Qui è la mia classe di test (più o meno):

public class ServiceExampleTest { 

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

Questo è sufficiente per generare l'eccezione. La classe FooServiceImpl restituisce un set di Foo, dove Foo è una classe di entità. Il metodo getFoos() funziona quando l'applicazione viene eseguita nel solito modo. Il problema viene solo nel contesto dei test unitari.

+0

Potrebbe pubblicare il tuo classe di test come bene? Non ho mai usato Spring Roo, ma con i normali test di Spring di solito devi estendere AbstractSpringJUnit4Test (o qualcosa del genere) o usare un runner Spring personalizzato tramite annotazione per i test. – ponzao

risposta

3

Questo è un problema incredibilmente fastidioso con Spring Roo e non ho trovato la soluzione ufficiale per.

Ma ... qui ci sono due soluzioni:

  • Copia il vaso primavera-aspetti al vostro progetto quindi aggiungerlo ai vostri progetti AspectJ Aspect Percorso
  • Usa Maven per eseguire il test di unità (e perdere la barra verde :()

per l'opzione un clic destro sul vostro progetto seleziona Proprietà-> AspectJ costruire -.> Aspetto Percorso Tab

+0

Accetterò questa risposta, ma non sono nella posizione di verificarla facilmente, poiché non uso più Roo. (Sono a un altro lavoro.) –

+0

@FarmBoy Non si può dire che senza dire cosa si sta utilizzando ora :) –

+0

Groovy/Grails. Lo adoro. –

6

ponzao è corretto sono in grado di. avere tutte le magie di iniezione primaverile avendo la mia classe di test estendere AbstractJunit4SpringContextTests.

ad es.

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

Sembra brutto, ma sembra funzionare per me. – kipz

1

La classe unit test dovrebbe avere @MockStaticEntityMethods annotazione.

0

Anche io stavo correndo nella stessa eccezione e tutto era configurato correttamente. Ho rimosso il progetto e reimportato di nuovo in STS (SpringSource Tool Suite) e questo problema è andato via.

Non sono sicuro del motivo per cui è stato risolto, ma questo problema potrebbe essere stato causato dall'uso di Eclipse per gestire il progetto generato da Roo prima di passare a STS nel mio caso.

3

La classe di test dell'unità deve avere l'annotazione @MockStaticEntityMethods.

Volevo solo aggiungere più dettagli alla risposta di cui sopra da @migue in quanto mi ci è voluto un po 'per capire come farlo funzionare. Il sito http://java.dzone.com/articles/mock-static-methods-using-spring-aspects mi ha davvero aiutato a ricavare la risposta qui sotto.

Ecco cosa ho fatto per iniettare il gestore di entità tramite la classe di test. Annota innanzitutto la tua classe di test con @MockStaticEntityMethods e crea la classe MockEntityManager (che è una classe che implementa semplicemente l'interfaccia EntityManager).

allora si può fare quanto segue nel ServiceExampleTest classe di test:

@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(); 
} 

Questo significa che quando hai chiamato fs.getFoos() l'AnnotationDrivenStaticEntityMockingControl sarà iniettato il vostro gestore di entità finto come Foo.entityManager() è una metodo statico.

noti inoltre che se fs.getFoos() chiama altri metodi statici su classi entità come Foo e Bar, devono anche essere specificati come parte di questo tipo di test.

Così, diciamo per esempio Foo aveva un metodo find statico chiamato "getAllBars (Long fooId)", che viene chiamato quando fs.getFoos() vengono chiamati, allora si avrebbe bisogno di fare quanto segue, al fine di rendere il lavoro AnnotationDrivenStaticEntityMockingControl.

@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(); 
} 

Ricordare l'AnnotationDrivenStaticEntityMockingControl deve essere nello stesso ordine in cui fs.getFoos() chiama i suoi metodi statici.

0

Molto tempo dopo la domanda, ma ho una soluzione di lavoro quando si cerca di eseguire unit test Spring Roo dall'interno di Eclipse ...

  1. Avere il progetto open in Eclipse
  2. In Eclipse, Progetto> Clean > Rebuild (automatico o manuale non importa)
  3. una volta che la ri-costruzione è completa, in una finestra di console, hanno pulito e ri-package (pulita è richiesto) Maven:

    mvn clean package

o se il test di unità non riescono a Maven (e avete bisogno di Eclipse per il debug i test)

mvn clean package -Dmaven.test.skip=true 

4. Una volta che il pacchetto è successo, quindi aggiornare di nuovo in Eclipse.

Dovresti essere in grado di eseguire correttamente i test delle unità in Eclipse. Ho riscontrato che le entità di modifica hanno causato la maggiore frequenza dell'errore del gestore entità. Quando mi sono limitato a modificarli, ho potuto modificare altre classi e i test di unità continuavano a funzionare correttamente.

0

questo ha funzionato per me 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 classe Indirizzo in questo modo:

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; 
}