116

JUnit4とスプリングテストライブラリを使用していくつかの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
4

18 に答える 18

129

私は同じ問題を抱えており(JUnitテストはMaven Surefireで失敗しましたが、Eclipseで合格しました)、pom.xmlのmavensurefire構成で常にforkModeを設定することで問題を解決できました。

<プラグイン>
    <groupId> org.apache.maven.plugins </ groupId>
    <artifactId> maven-surefire-plugin </ ArtifactId>
    <バージョン>2.12</バージョン>
    <構成>
        <forkMode>常に</forkMode>
    </ configuration>
</プラグイン>

Surefireパラメーター: http: //maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html

編集(2014年1月):

PeterPerháčが指摘したように、forkModeパラメーターはSurefire2.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>

詳細については、フォークオプションと並列テストの実行を参照してください。

于 2012-03-22T15:22:56.533 に答える
8

私は突然このエラーを経験しました、そして私にとっての解決策はテストを並行して実行することを無効にすることでした。

「クラス」による並列テストを実行するようにsurefireを構成することで、失敗するテストの数を減らすことができるため、マイレージは異なる場合があります。

            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <configuration>
                    <parallel>classes</parallel>
                    <threadCount>10</threadCount>
                </configuration>
            </plugin>

最初に書いたように、これは私のテストスイートには十分ではなかったので、<configuration>セクションを削除して並列を完全に無効にしました。

于 2011-09-26T08:25:15.223 に答える
7

同様の問題がありまし@Autowiredた.Mavenコマンドラインを使用すると、テストコードの注釈が機能しませんでしたが、Eclipseでは正常に機能しました。JUnit のバージョンを 4.4 から 4.9 に更新しただけで、問題は解決しました。

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.1</version>
</dependency>
于 2012-03-13T09:15:51.550 に答える
5

これはあなたの状況に正確には当てはまりませんが、私は同じことをしました-Mavenからのテスト目標が実行されたときにEclipseで合格するテストは失敗しました。

それは私のスイートの以前の別のパッケージでのテストであることが判明しました。これは私が解決するのに1週間かかりました!

以前のテストでは、いくつかのLogbackクラスをテストし、構成ファイルからLogbackコンテキストを作成しました。

後のテストはSpringのSimpleRestTemplateのサブクラスをテストし、どういうわけか、DEBUGをオンにして前のLogbackコンテキストを保持しました。これにより、RestTemplateでHttpStatusなどをログに記録するための追加の呼び出しが行われました。

このような状況に陥ったことがあるかどうかを確認するのもまた別のことです。Logbackテストクラスにいくつかのモックを挿入して問題を修正し、実際のLogbackコンテキストが作成されないようにしました。

于 2012-01-19T22:10:56.460 に答える
5

同様の問題がありますが、IntelliJ IDEA + Maven + TestNG + 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>
于 2011-07-26T10:51:32.083 に答える
3

私は同じ問題を抱えていましたが、私にとっての問題は、Eclipse では Java アサーション (たとえば assert(num > 0)) が有効になっておらず、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)
于 2013-01-21T16:59:03.563 に答える
2

[ここのスタックトレースは少し異なって見えるため、これが元の質問に対する回答であるかどうかはわかりませんが、他の人にとっては役立つかもしれません。]

Cobertura も実行している場合 (コード カバレッジ レポートを取得するため)、Surefire でテストが失敗することがあります。これは、Cobertura が (コードの使用を測定するために) プロキシを必要とし、それらと Spring プロキシの間にある種の競合があるためです。これは、Spring が cglib2 を使用する場合にのみproxy-target-class="true"発生します。これは、たとえば、 を持っている場合、またはインターフェイスを実装していないプロキシされているオブジェクトがある場合に当てはまります。

これに対する通常の修正は、インターフェースを追加することです。したがって、たとえば、DAO は、DAOImpl クラスによって実装されるインターフェイスである必要があります。インターフェースで自動接続すると、すべて正常に動作します (cglib2 が不要になったためです。代わりに、より単純な JDK プロキシをインターフェースに使用でき、Cobertura はこれで正常に動作します)。

ただし、注釈付きコントローラーでインターフェースを使用することはできません (サーブレットでコントローラーを使用しようとすると、実行時エラーが発生します) - コントローラーを自動配線する Cobertura + Spring テストのソリューションがありません。

于 2012-03-23T13:54:14.570 に答える
1

これは、問題のトラブルシューティングに役立ちました。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>

これが確実なプラグインのトラブルシューティングに役立つことを願っています。

于 2013-09-17T05:09:43.260 に答える
1

今日、を含むオブジェクトをMapJSON 文字列に変換するメソッドをテストして、この問題が発生しました。Eclipse と Maven Surefire プラグインは、HashMap順序付けなどの実装が異なる異なる JRE を使用していたため、Eclipse を介して実行されたテストが成功し、surefire を介して実行されたテストが失敗 (assertEquals失敗) したと思います。最も簡単な解決策は、信頼できる順序付けを持つ Map の実装を使用することでした。

于 2012-03-15T08:27:06.890 に答える
0

通常、テストがEclipseで成功し、Mavenで失敗する場合、これは2つの主な違いであるため、クラスパスの問題です。

したがって、maven -X testを使用してクラスパスを確認し、メニューまたはプロジェクトのルートにある.classpathファイルでeclipseのクラスパスを確認できます。

たとえば、personservice-test.xmlがクラスパスに含まれていることを確認しますか?

于 2010-07-29T18:35:06.457 に答える
0

EntityManagerFactoryにはすでにデータソースがあるため、JpaTransactionManagerにデータソースを挿入する必要はありません。次のことを試してください。

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
   <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
于 2010-07-29T18:26:41.750 に答える
0

私は同じ問題を抱えていましたが、私にとっての解決策は、Maven がローカル jar を含むすべての依存関係を処理できるようにすることでした。オンラインの依存関係には Maven を使用し、ローカルの依存関係にはビルド パスを手動で構成しました。したがって、Maven は手動で構成した依存関係を認識していませんでした。

このソリューションを使用して、ローカルの jar 依存関係を Maven にインストールしました。

Mavenプロジェクトにローカルjarファイルを追加するには?

于 2015-01-19T09:42:32.127 に答える
-2

ほとんどの場合、構成ファイルはsrc/main/resourcesにありますが、maven で正しく動作するにはsrc/test/resourcesの下にある必要があります。

https://cwiki.apache.org/UIMA/differences-between-running-unit-tests-in-eclipse-and-in-maven.html

ここでこの答えを見つけることができなかったので、2年後にこれに返信していますが、それが正しいと思います.

于 2012-08-06T15:54:52.533 に答える