我正在尝试为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测试注入实体管理器吗?
这是我的Test类(或多或少):
public class ServiceExampleTest {
@Test
public void testFoo() {
FooService fs = new FooServiceImpl();
Set<Foo> foos = fs.getFoos();
}
}
这足以抛出异常。 FooServiceImpl类返回一个Foo,其中Foo是一个实体类。当应用程序以通常方式运行时,getFoos()
方法有效。问题只出在单元测试的背景下。
答案 0 :(得分:6)
ponzao是对的。通过让我的测试类扩展AbstractJunit4SpringContextTests,我能够拥有所有弹簧注入魔法。
e.g。
@ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" })
public class SelfRegistrationTest extends AbstractJUnit4SpringContextTests {
答案 1 :(得分:3)
对于Spring Roo来说,这是一个令人难以置信的恼人问题,我还没有想出正式的解决方案。
但是......这里有两个解决方法:
对于选项1右键单击您的项目,选择Properties-&gt; AspectJ Build - &gt; Aspect Path选项卡。
答案 2 :(得分: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)”的静态find方法,当调用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()调用其静态方法的顺序相同。
答案 3 :(得分:1)
您的单元测试类应该有@MockStaticEntityMethods注释。
答案 4 :(得分:0)
我也遇到了同样的异常,一切都配置正确。我删除了项目并在STS(SpringSource Tool Suite)中再次重新导入它,这个问题就消失了。
不确定为什么要修复它,但是这个问题可能是由于在我的情况下切换到STS之前使用Eclipse来管理Roo生成的项目。
答案 5 :(得分:0)
问题发布后很长时间,但是当我尝试从Eclipse中运行Spring Roo单元测试时,我有一个有效的解决方案......
重新构建完成后,在控制台窗口中,让Maven清理并重新打包(需要清理):
mvn clean package
或者如果您的单元测试在maven中失败(并且您需要Eclipse来调试测试)
mvn clean package -Dmaven.test.skip=true
4。一旦包成功,然后在Eclipse中刷新。
您现在应该能够在Eclipse中成功运行单元测试。我发现编辑实体导致了实体管理器错误的最大频率。当我没有编辑它们时,我可以编辑其他类,单元测试将继续成功运行。
答案 6 :(得分: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');
}
}
}
使用这样的Address类:
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;
}