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
私は同じ問題を抱えていて(JUnitテストはMaven Surefireで失敗しましたがEclipseで合格しました)、forkModeをalwayspom.xmlのmaven surefire構成:
<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月):
PeterPerháč が指摘したように、forkModeパラメーターはSurefire 2.14から非推奨になりました。 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>
詳細については、「 フォークオプションと並列テスト実行 」を参照してください。
同様の問題がありました。テストコード内の注釈@Autowired
は、Mavenコマンドラインを使用すると機能しませんが、Eclipseで正常に機能しました。 JUnitバージョンを4.4から4.9に更新しただけで、問題は解決しました。
<dependency>
<groupId>junit</groupId
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
突然このエラーが発生しましたが、解決策は、テストを並行して実行できないようにすることでした。
「クラス」で並列テストを実行するようにシュアファイアを設定することで、失敗するテストの数を減らすことができるため、あなたの走行距離は異なる場合があります。
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<configuration>
<parallel>classes</parallel>
<threadCount>10</threadCount>
</configuration>
</plugin>
最初に書いたように、これはテストスイートには不十分であったため、<configuration>
セクション。
私は同様の問題を抱えていますが、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>
これはあなたの状況にはまったく当てはまりませんが、私は同じことをしました-Mavenからのテスト目標が実行されると、Eclipseで合格するテストは失敗しました。
それは私のスイートで以前のテストであることが判明しました別のパッケージで。これを解決するのに1週間かかりました!
以前のテストでは、いくつかのLogbackクラスをテストし、構成ファイルからLogbackコンテキストを作成しました。
後のテストでは、SpringのSimpleRestTemplateのサブクラスをテストし、どういうわけか、以前のLogbackコンテキストはDEBUGをオンにして保持されていました。これにより、HttpStatusなどを記録するためにRestTemplateで追加の呼び出しが行われました。
この状況に陥ったかどうかを確認することは別のことです。実際のLogbackコンテキストが作成されないように、Logbackテストクラスにモックを挿入することで問題を修正しました。
私は同じ問題を抱えていましたが、私にとっての問題はJavaアサーション(例:assert(num> 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)
同じような問題があり、原因も解決策も異なります。私の場合、実際にはシングルトンオブジェクトのメンバー変数がスレッドセーフでない方法で変更されているというエラーが発生しました。この場合、受け入れられた回答に従い、並行テストを回避すると、テストによって実際に明らかになったエラーのみが非表示になります。もちろん、私の解決策は、コードにこのような悪い振る舞いがないように設計を修正することです。
JUnit run
およびmaven install
とは異なるテスト実行結果は、いくつかの問題の症状のようです。
テストの実行を再利用するスレッドを無効にしても、このケースの症状は解消されましたが、コードがスレッドセーフではないという印象は依然として強かったです。
私たちの場合、違いは、テスト動作を変更したBeanの存在によるものでした。 JUnitテストだけを実行すると問題ありませんが、プロジェクトinstall
ターゲットを実行すると、テストケースが失敗します。開発中のテストケースであったため、すぐに疑わしいものになりました。
その結果、別のテストケースが、新しいテストケースの実行まで存続するSpringを介してBeanをインスタンス化していました。 Beanの存在は、一部のクラスの動作を変更し、失敗した結果を生成していました。
私たちの場合の解決策は、そもそも必要ではなかったBeanを取り除くことでした(copy + paste gunからの別の賞品)。
この症状のある人は誰でも根本原因を調査することをお勧めします。テスト実行でスレッドの再利用を無効にすると、スレッドが非表示になるだけです。
[ここでのスタックトレースは少し異なるように見えるので、これが元の質問への回答であるかどうかはわかりませんが、他の人にとっては役に立つかもしれません。]
Coberturaを実行している場合(コードカバレッジレポートを取得するため)、Surefireでテストが失敗する可能性があります。これは、Coberturaが(コードの使用を測定するために)プロキシを必要とし、それらとSpringプロキシの間に何らかの競合があるためです。こののみは、Springがcglib2を使用する場合に発生します。たとえば、proxy-target-class="true"
、またはインターフェイスを実装しないプロキシされているオブジェクトがある場合。
これに対する通常の修正は、インターフェースを追加することです。したがって、たとえば、DAOは、DAOImplクラスによって実装されるインターフェイスである必要があります。インターフェイスで自動配線すると、すべてが正常に機能します(cglib2が不要になったため、代わりにインターフェイスへのより単純なJDKプロキシを使用でき、Coberturaはこれで問題なく動作します)。
ただし、注釈付きコントローラーでインターフェースを使用することはできません(サーブレットでコントローラーを使用しようとすると、ランタイムエラーが発生します)-コントローラーを自動配線するCobertura + Springテストのソリューションがありません。
同様の問題がありました。MavenSurefireでJUnitテストが失敗しましたが、SpringSource Bundle RepositoryのJUnitライブラリバージョン4.11.0を使用すると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>
今日、Map
を含むオブジェクトをJSON文字列に変換するメソッドをテストするときにこの問題が発生しました。 EclipseとMaven surefireプラグインはHashMap
順序付けなどの異なる実装を持つ異なるJREを使用していたため、Eclipseで実行されるテストはパスし、surefireで実行されるテストは失敗します(assertEquals
失敗)。最も簡単な解決策は、信頼できる順序のMapの実装を使用することでした。
これは私の問題のトラブルシューティングに役立ちました。私は同様の症状がありましたが、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プラグインのトラブルシューティングに役立つことを願っています。
私は同じ問題を抱えていましたが、私にとっての解決策は、Mavenがローカルjarを含むすべての依存関係を処理できるようにすることでした。オンライン依存関係にはMavenを使用し、ローカル依存関係にはビルドパスを手動で構成しました。したがって、Mavenは、手動で構成した依存関係を認識していませんでした。
このソリューションを使用して、ローカルjar依存関係をMavenにインストールしました。
EntityManagerFactoryにはすでにデータソースがあるため、JpaTransactionManagerにDataSourceを注入する必要はありません。以下を試してください:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
通常、テストがEclipseで成功し、mavenで失敗すると、クラスパスの問題になります。これは、両者の主な違いだからです。
そのため、maven -X testでクラスパスをチェックし、メニューまたはプロジェクトのルートにある.classpathファイルでEclipseのクラスパスをチェックできます。
たとえば、personservice-test.xmlがクラスパスにあると確信していますか?