6

我正在尝试为 Spring Roo 项目编写 JUnit 测试。如果我的测试需要使用实体类,我会得到以下异常:

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

Spring Aspects JAR 看起来配置正确。特别是,我在pom.xml文件中有以下内容:

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

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

当不从 JUnit 测试中调用时,使用实体类的类工作正常。知道如何设置以便从 JUnit 测试中注入实体管理器吗?

这是我的测试课(或多或少):

public class ServiceExampleTest {

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

这足以引发异常。FooServiceImpl 类返回一组 Foo,其中 Foo 是一个实体类。getFoos()当应用程序以通常的方式运行时,该方法有效。问题仅出现在单元测试的上下文中。

4

7 回答 7

6

ponzao 是正确的。通过让我的测试类扩展 AbstractJunit4SpringContextTests,我能够拥有所有的弹簧注入魔法。

例如

@ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" })
public class SelfRegistrationTest extends AbstractJUnit4SpringContextTests {
于 2010-11-11T17:08:27.983 回答
3

这是 Spring Roo 的一个非常烦人的问题,我还没有找到官方的解决方案。

但是......这里有两种解决方法:

  • 将 spring-aspects jar 复制到您的项目中,然后将其添加到您的 Projects AspectJ Aspect Path
  • 使用 Maven 运行您的单元测试(并错过绿色条 :( )

对于选项一,右键单击您的项目,选择 Properties-> AspectJ Build -> Aspect Path Tab。

于 2010-11-07T22:46:18.887 回答
3

您的单元测试类应该有 @MockStaticEntityMethods 注释。

只是想为@migue 的上述答案添加更多细节,因为我花了一段时间才弄清楚如何让它工作。网站http://java.dzone.com/articles/mock-static-methods-using-spring-aspects确实帮助我得出了下面的答案。

这是我通过测试类注入实体管理器所做的。首先用 @MockStaticEntityMethods 注释你的测试类并创建 MockEntityManager 类(这是一个只实现 EntityManager 接口的类)。

然后您可以在 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();
}

这意味着当您调用 fs.getFoos() 时, AnnotationDrivenStaticEntityMockingControl 将注入您的模拟实体管理器,因为 Foo.entityManager() 是一个静态方法。

另请注意,如果fs.getFoos() 调用实体类(如 Foo 和 Bar)上的其他静态方法,它们也必须指定为本测试用例的一部分。

例如,Foo 有一个名为“getAllBars(Long fooId)”的静态查找方法,当调用 fs.getFoos() 时会调用该方法,那么您需要执行以下操作才能使 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();
}

请记住 AnnotationDrivenStaticEntityMockingControl 必须与 fs.getFoos() 调用其静态方法的顺序相同。

于 2012-11-14T15:25:09.567 回答
1

您的单元测试类应该有 @MockStaticEntityMethods 注释。

于 2010-11-16T14:03:09.937 回答
0

我也遇到了同样的异常,一切都配置正确。我删除了该项目并在 STS(SpringSource 工具套件)中再次重新导入它,这个问题就消失了。

不知道为什么这会解决它,但在我的情况下,这个问题可能是由于在切换到 STS 之前使用 Eclipse 来管理 Roo 生成的项目造成的。

于 2011-05-08T09:09:25.067 回答
0

问题提出很长时间后,但是当我尝试从 Eclipse 中运行 Spring Roo 单元测试时,我有一个可行的解决方案......

  1. 在 Eclipse 中打开项目
  2. 在 Eclipse 中,Project > Clean > Rebuild(自动或手动无关紧要)
  3. 重新构建完成后,在控制台窗口中,清理并重新打包 Maven(需要清理):

    mvn clean package

或者如果您的单元测试在 Maven 中失败(并且您需要 Eclipse 来调试您的测试)

  mvn clean package -Dmaven.test.skip=true

4. 打包成功后,在 Eclipse 中刷新。

您现在应该能够在 Eclipse 中成功运行单元测试。我发现编辑实体导致实体管理器错误的频率最高。当我不再编辑它们时,我可以编辑其他类并且单元测试将继续成功运行。

于 2014-04-27T18:52:29.500 回答
0

这对我使用 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');
        }
    }
}

使用这样的地址类:

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;
}
于 2015-09-13T00:00:06.253 回答