How to use JUnit tests with Spring Roo? (Problems with EntityManager)

后端 未结 7 516
忘了有多久
忘了有多久 2021-01-02 19:40

I\'m trying to write a JUnit test for a Spring Roo project. If my test requires use of the entity classes, I get the following Exception:

java.lang.IllegalS         


        
相关标签:
7条回答
  • 2021-01-02 20:18

    Your unit test class should have @MockStaticEntityMethods annotation.

    0 讨论(0)
  • 2021-01-02 20:19

    ponzao is correct. I am able to have all the spring injection magic by having my test class extend AbstractJunit4SpringContextTests.

    e.g.

    @ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" })
    public class SelfRegistrationTest extends AbstractJUnit4SpringContextTests {
    
    0 讨论(0)
  • 2021-01-02 20:25

    This is an incredibly annoying problem with Spring Roo and I have not figured out the official solution for.

    But ... here are two workarounds:

    • Copy the spring-aspects jar to your project then add it to your Projects AspectJ Aspect Path
    • Use Maven to run your unit tests (and miss the green bar :( )

    For option one Right click on your project select Properties-> AspectJ Build -> Aspect Path Tab.

    0 讨论(0)
  • 2021-01-02 20:25

    Long time after the question but I have a working solution when trying to run Spring Roo unit tests from within Eclipse...

    1. Have the project open in Eclipse
    2. In Eclipse, Project > Clean > Rebuild (Automatic or Manual doesn't matter)
    3. Once the re-build is complete, in a console window, have Maven clean and re-package (Clean is required):

      mvn clean package

    or if your unit tests are failing in maven (and you need Eclipse for debugging your tests)

      mvn clean package -Dmaven.test.skip=true
    

    4. Once the package is successful, then refresh back in Eclipse.

    You should be able to run unit tests successfully back in Eclipse now. I found editing entities caused the greatest frequency of the entity manager error. When I stayed clear of editing them, I could edit other classes and unit tests would continue to run successfully.

    0 讨论(0)
  • 2021-01-02 20:26

    Your unit test class should have @MockStaticEntityMethods annotation.

    Just wanted to add more detail to the above answer by @migue as it took me a while to figure out how to get it to work. The site http://java.dzone.com/articles/mock-static-methods-using-spring-aspects really helped me to derive the answer below.

    Here is what I did to inject entity manager via test class. Firstly annotate your test class with @MockStaticEntityMethods and create MockEntityManager class (which is a class that just implements EntityManager interface).

    Then you can do the following in your ServiceExampleTest test class:

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

    This means when you called fs.getFoos() the AnnotationDrivenStaticEntityMockingControl will have injected your mock entity manager as Foo.entityManager() is a static method.

    Also note that if fs.getFoos() calls other static methods on Entity classes like Foo and Bar, they must also be specified as part of this test case.

    So say for example Foo had a static find method called "getAllBars(Long fooId)" which gets called when fs.getFoos() get called, then you would need to do the following in order to make AnnotationDrivenStaticEntityMockingControl work.

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

    Remember the AnnotationDrivenStaticEntityMockingControl must be in the same order that fs.getFoos() calls its static methods.

    0 讨论(0)
  • 2021-01-02 20:41

    This worked for me with 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');
            }
        }
    }
    

    With Address class like this:

    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;
    }
    
    0 讨论(0)
提交回复
热议问题