我已经使用JUnit 4和spring-test库编写了一些JUnit测试。当我在Eclipse中运行测试然后运行正常并通过。但是当我使用Maven运行它们时(在构建过程中),它们无法给出与弹簧相关的错误。我不确定导致问题的是什么,JUnit,Surefire或Spring。这是我的测试代码,弹簧配置以及我从Maven获得的异常:
PersonServiceTest.java
package com.xyz.person.test;
import static com.xyz.person.util.FjUtil.toFjList;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
import com.xyz.person.bo.Person;
import com.xyz.person.bs.PersonService;
import fj.Effect;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:personservice-test.xml" })
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
public class PersonServiceTest {
@Autowired
private PersonService service;
@Test
@Transactional
public void testCreatePerson() {
Person person = new Person();
person.setName("abhinav");
service.createPerson(person);
assertNotNull(person.getId());
}
@Test
@Transactional
public void testFindPersons() {
Person person = new Person();
person.setName("abhinav");
service.createPerson(person);
List<Person> persons = service.findPersons("abhinav");
toFjList(persons).foreach(new Effect<Person>() {
public void e(final Person p) {
assertEquals("abhinav", p.getName());
}});
}
}
personservice-的test.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<import resource="classpath:/personservice.xml" />
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
lazy-init="true">
<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="url" value="jdbc:derby:InMemoryDatabase;create=true" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="persistenceUnitName" value="PersonService" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.DerbyDialect" />
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.validator.autoregister_listeners" value="false" />
<entry key="javax.persistence.transactionType" value="RESOURCE_LOCAL" />
</map>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="datasource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="false" />
<bean id="beanMapper" class="org.dozer.DozerBeanMapper">
<property name="mappingFiles">
<list>
<value>personservice-mappings.xml</value>
</list>
</property>
</bean>
</beans>
Maven中的异常
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.xyz.person.test.PersonServiceTest
23:18:51,250 WARN JDBCExceptionReporter:77 - SQL Warning: 10000, SQLState: 01J01
23:18:51,281 WARN JDBCExceptionReporter:78 - Database 'InMemoryDatabase' not created, connection made to existing database instead.
23:18:52,937 WARN JDBCExceptionReporter:77 - SQL Warning: 10000, SQLState: 01J01
23:18:52,937 WARN JDBCExceptionReporter:78 - Database 'InMemoryDatabase' not created, connection made to existing database instead.
23:18:52,953 WARN TestContextManager:429 - Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@359a359a] to process 'after' execution for test: method [public void com.xyz.person.test.PersonServiceTest.testCreatePerson()], instance [com.xyz.person.test.PersonServiceTest@1bc81bc8], exception [org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! JpaTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single JpaTransactionManager for all transactions on a single DataSource, no matter whether JPA or JDBC access.]
java.lang.IllegalStateException: No value for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@3f563f56] bound to thread [main]
at org.springframework.transaction.support.TransactionSynchronizationManager.unbindResource(TransactionSynchronizationManager.java:199)
at org.springframework.orm.jpa.JpaTransactionManager.doCleanupAfterCompletion(JpaTransactionManager.java:489)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.cleanupAfterCompletion(AbstractPlatformTransactionManager.java:1011)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:804)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.endTransaction(TransactionalTestExecutionListener.java:515)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.endTransaction(TransactionalTestExecutionListener.java:290)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:183)
at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:426)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:90)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:59)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:115)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:102)
at org.apache.maven.surefire.Surefire.run(Surefire.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:599)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)
23:18:53,078 WARN TestContextManager:377 - Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@359a359a] to process 'before' execution of test method [public void com.xyz.person.test.PersonServiceTest.testFindPersons()] for test instance [com.xyz.person.test.PersonServiceTest@79f279f2]
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! JpaTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single JpaTransactionManager for all transactions on a single DataSource, no matter whether JPA or JDBC access.
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:304)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.startTransaction(TransactionalTestExecutionListener.java:507)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.startNewTransaction(TransactionalTestExecutionListener.java:269)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.beforeTestMethod(TransactionalTestExecutionListener.java:162)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:374)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:59)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:115)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:102)
at org.apache.maven.surefire.Surefire.run(Surefire.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:599)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)
Tests run: 3, Failures: 0, Errors: 3, Skipped: 0, Time elapsed: 15.625 sec <<< FAILURE!
Results :
Tests in error:
testCreatePerson(com.xyz.person.test.PersonServiceTest)
testCreatePerson(com.xyz.person.test.PersonServiceTest)
testFindPersons(com.xyz.person.test.PersonServiceTest)
Tests run: 3, Failures: 0, Errors: 3, Skipped: 0
答案 0 :(得分:88)
我遇到了同样的问题(JUnit测试在Maven Surefire中失败但在Eclipse中传递)并设法通过在maven surefire配置中将 forkMode 设置为始终来解决它pom.xml中:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.12</version> <configuration> <forkMode>always</forkMode> </configuration> </plugin>
Surefire参数:http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html
修改(2014年1月):
正如Peter Perháč指出的那样,自Surefire 2.14起不推荐使用forkMode参数。从Surefire 2.14开始改为使用:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<reuseForks>false</reuseForks>
<forkCount>1</forkCount>
</configuration>
</plugin>
有关详细信息,请参阅Fork Options and Parallel Test Execution
答案 1 :(得分:7)
我突然遇到了这个错误,我的解决方案就是禁用并行运行测试。
你的milage可能会有所不同,因为我可以通过配置surefire以'class'运行并行测试来降低失败测试的数量。:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<configuration>
<parallel>classes</parallel>
<threadCount>10</threadCount>
</configuration>
</plugin>
正如我先写的那样,这对我的测试套件来说还不够,所以我通过删除<configuration>
部分完全禁用了并行。
答案 2 :(得分:7)
我遇到了类似的问题,测试代码中的注释@Autowired
在使用Maven命令行时无效,而在Eclipse中工作正常。我只是将我的JUnit版本从4.4更新到4.9,问题解决了。
<dependency>
<groupId>junit</groupId
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
答案 3 :(得分:5)
我有类似的问题,但使用IntelliJ IDEA + Maven + TestNG + spring-test。 ( spring-test 当然是必不可少的:)) 当我更改 maven-surefire-plugin 的配置以并行禁用运行测试时,它已得到修复。像这样:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<skipTests>${maven.test.skip}</skipTests>
<trimStackTrace>false</trimStackTrace>
<!--<parallel>methods</parallel>-->
<!-- to skip integration tests -->
<excludes>
<exclude>**/IT*Test.java</exclude>
<exclude>**/integration/*Test.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skipTests>${maven.integration-test.skip}</skipTests>
<!-- Make sure to include this part, since otherwise it is excluding Integration tests -->
<excludes>
<exclude>none</exclude>
</excludes>
<includes>
<include>**/IT*Test.java</include>
<include>**/integration/*Test.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
答案 4 :(得分:4)
这并不完全适用于您的情况,但我有同样的事情 - 当运行Maven的测试目标时,Eclipse中传递的测试失败。
结果是我的套件中的早期测试,在不同的包中。这花了我一个星期才解决!
早期的测试是测试一些Logback类,并从配置文件创建一个Logback上下文。
后来的测试是测试Spring的SimpleRestTemplate的子类,不知何故,早期的Logback上下文被保持,DEBUG on。这导致在RestTemplate中进行额外调用以记录HttpStatus等。
检查是否有人遇到这种情况是另一回事。我通过在我的Logback测试类中注入一些Mocks来修复我的问题,因此没有创建真正的Logback上下文。
答案 5 :(得分:3)
我遇到了同样的问题,但对我来说问题是Java断言(例如assert(num&gt; 0))没有为Eclipse启用,但在运行maven时启用了。
因此,从Eclipse运行jUnit测试没有捕获触发断言错误。
使用jUnit 4.11(与我使用的旧版本相反)时会明确这一点,因为它会打印出断言错误,例如
java.lang.AssertionError: null
at com.company.sdk.components.schema.views.impl.InputViewHandler.<init>(InputViewHandler.java:26)
at test.com.company.sdk.util.TestSchemaExtractor$MockInputViewHandler.<init>(TestSchemaExtractor.java:31)
at test.com.company.sdk.util.TestSchemaExtractor.testCreateViewToFieldsMap(TestSchemaExtractor.java:48)
答案 6 :(得分:3)
我有一个类似的问题,因为不同的原因,因此有不同的解决方案。在我的情况下,我实际上有一个错误,其中单个对象具有以非线程安全方式修改的成员变量。在这种情况下,遵循接受的答案并绕过并行测试只会隐藏测试实际显示的错误。当然,我的解决方案是修复设计,以便在代码中不会出现这种不良行为。
答案 7 :(得分:2)
[我不确定这是原始问题的答案,因为这里的堆栈跟踪看起来略有不同,但它可能对其他人有用。]
当您还在运行Cobertura(获取代码覆盖率报告)时,您可以在Surefire中进行测试失败。这是因为Cobertura需要代理(测量代码使用),并且这些代理与Spring代理之间存在某种冲突。当Spring使用cglib2时会出现 only ,例如,如果你有proxy-target-class="true"
,或者你有一个被代理的对象没有实现接口,那就是这种情况。 / p>
正常的解决方法是添加界面。因此,例如,DAO应该是接口,由DAOImpl类实现。如果你在界面上自动装配,一切都会正常工作(因为不再需要cglib2;可以使用更简单的接口JDK代理,Cobertura可以正常工作)。
但是,您不能使用带注释控制器的接口(尝试在servlet中使用控制器时会出现运行时错误) - 我没有针对自动装配控制器的Cobertura + Spring测试的解决方案。
答案 8 :(得分:2)
与JUnit run
和maven install
不同的测试执行结果似乎是几个问题的症状。
禁用线程重用测试执行也消除了我们的情况中的症状,但是代码不是线程安全的印象仍然很强。
在我们的例子中,差异是由于存在修改测试行为的bean。只运行JUnit测试会很好,但运行项目install
目标会导致测试用例失败。由于它是正在开发的测试用例,因此立即引起怀疑。
结果是另一个测试用例是通过Spring实例化一个bean,它将一直存在,直到执行新的测试用例。 bean存在正在修改某些类的行为并产生失败的结果。
在我们的案例中,解决方案是摆脱豆子,这首先不需要(来自复制+粘贴枪的另一个奖励)。
我建议有这种症状的每个人调查根本原因是什么。在测试执行中禁用线程重用可能只会隐藏它。
答案 9 :(得分:2)
我遇到了类似的问题:当我使用SpringSource Bundle Repository的JUnit库版本4.11.0时,JUnit测试在Maven Surefire中失败但在Eclipse中传递。格外:
<dependency>
<groupId>org.junit</groupId>
<artifactId>com.springsource.org.junit</artifactId>
<version>4.11.0</version>
</dependency>
然后我用以下JUnit库版本4.11替换它,一切正常。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
答案 10 :(得分:1)
今天我遇到了这个问题,测试了一个方法,该方法将包含Map
的对象转换为JSON字符串。我假设Eclipse和Maven surefire插件使用了不同的JRE,这些JRE具有HashMap
排序的不同实现,这导致测试通过Eclipse传递,测试通过surefire失败(assertEquals
失败)。最简单的解决方案是使用具有可靠排序的Map实现。
答案 11 :(得分:0)
通常当测试在eclipse中传递并且使用maven失败时,这是一个类路径问题,因为它是两者之间的主要区别。
因此,您可以使用maven -X test检查类路径,并通过菜单或项目根目录中的.classpath文件检查eclipse的类路径。
您确定,例如personservice-test.xml是否在类路径中?
答案 12 :(得分:0)
我遇到了类似的问题,我运行测试时禁用了这样的分叉
mvn clean test -DreuseForks=false
问题就消失了。 缺点是整体测试执行时间会更长,这就是为什么您可能只想在必要时从命令行执行此操作
答案 13 :(得分:0)
就我而言,原因是代码中的错误。该测试依赖于HashSet
中元素的特定顺序,事实证明在Eclipse或Maven Surefire中运行时元素都是不同的。
答案 14 :(得分:0)
我遇到了同样的问题,我的解决方案是允许Maven处理所有依赖项,包括本地jar。我使用Maven进行在线依赖,并为本地依赖项手动配置构建路径。 因此,Maven不知道我手动配置的依赖项。
我使用此解决方案将本地jar依赖项安装到Maven中:
答案 15 :(得分:0)
这有助于我解决问题。我有类似的症状,因为maven会失败,但运行junit测试运行正常。
事实证明,我的父pom.xml包含以下定义:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<forkMode>pertest</forkMode>
<argLine>-Xverify:none</argLine>
</configuration>
</plugin>
在我的项目中,我重写它以删除argLine:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>pertest</forkMode>
<argLine combine.self="override"></argLine>
</configuration>
</plugin>
希望这有助于某人对surefire插件进行故障排除。
答案 16 :(得分:0)
您不需要在JpaTransactionManager中注入DataSource,因为EntityManagerFactory已经有一个数据源。请尝试以下方法:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
答案 17 :(得分:-2)
您的配置文件很可能位于 src / main / resources 中,而它们必须位于 src / test / resources 下才能在maven下正常工作。< / p>
https://cwiki.apache.org/UIMA/differences-between-running-unit-tests-in-eclipse-and-in-maven.html
我在两年后回答这个问题,因为我在这里找不到这个答案,我认为这是正确的答案。