Ich habe einige JUnit-Tests mit JUnit 4 und Spring-Test-Bibliotheken geschrieben. Wenn ich die Tests in Eclipse ausführe, laufen sie gut und bestehen. Wenn ich sie jedoch mit Maven ausführe (während des Erstellungsprozesses), geben sie keinen federbezogenen Fehler aus. Ich bin nicht sicher, was das Problem verursacht, JUnit, Surefire oder Spring. Hier ist mein Testcode, die Federkonfiguration und die Ausnahme, die ich von Maven bekomme:
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());
}});
}
}
Personen Service-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>
Ausnahme in 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
Antworten:
Ich hatte das gleiche Problem (JUnit-Tests in Maven Surefire fehlgeschlagen, aber in Eclipse bestanden) und konnte es lösen, indem ich forkMode in pom.xml auf immer in der Maven-Surefire- Konfiguration setzte:
Surefire-Parameter: http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html
Bearbeiten (Januar 2014):
Wie Peter Perháč betonte, ist der Parameter forkMode seit Surefire 2.14 veraltet. Verwenden Sie ab Surefire 2.14 stattdessen Folgendes:
Weitere Informationen finden Sie unter Gabeloptionen und parallele Testausführung
quelle
Dieser Fehler trat plötzlich auf, und die Lösung für mich bestand darin, die parallele Ausführung von Tests zu deaktivieren.
Ihr Kilometerstand kann variieren, da ich die Anzahl der fehlgeschlagenen Tests verringern könnte, indem ich todsicher konfiguriere, um parallele Tests nach Klassen durchzuführen:
Wie ich zuerst schrieb, war dies für meine Testsuite nicht ausreichend, daher habe ich parallel durch Entfernen des
<configuration>
Abschnitts vollständig deaktiviert .quelle
Ich hatte ein ähnliches Problem. Die Anmerkung
@Autowired
im Testcode funktionierte nicht unter Verwendung der Maven-Befehlszeile, während sie in Eclipse einwandfrei funktionierte. Ich habe gerade meine JUnit-Version von 4.4 auf 4.9 aktualisiert und das Problem wurde behoben.quelle
Dies trifft nicht genau auf Ihre Situation zu, aber ich hatte das Gleiche - Tests, die in Eclipse bestanden wurden, schlugen fehl, als das Testziel von Maven ausgeführt wurde.
Es stellte sich heraus, dass es sich früher in meiner Suite um einen Test in einem anderen Paket handelte . Ich habe eine Woche gebraucht, um es zu lösen!
Ein früherer Test testete einige Logback-Klassen und erstellte einen Logback-Kontext aus einer Konfigurationsdatei.
Der spätere Test testete eine Unterklasse von Spring's SimpleRestTemplate, und irgendwie wurde der frühere Logback-Kontext mit aktiviertem DEBUG gehalten. Dies führte dazu, dass in RestTemplate zusätzliche Aufrufe zum Protokollieren von HttpStatus usw. getätigt wurden.
Es ist eine andere Sache zu überprüfen, ob man jemals in diese Situation gerät. Ich habe mein Problem behoben, indem ich einige Mocks in meine Logback-Testklasse eingefügt habe, sodass keine echten Logback-Kontexte erstellt wurden.
quelle
Ich habe das ähnliche Problem, aber mit IntelliJ IDEA + Maven + TestNG + Federtest. ( Frühlingstest ist natürlich wichtig :)) Es wurde behoben, als ich die Konfiguration des Maven-Surefire-Plugins geändert habe , um parallel laufende Tests zu deaktivieren. So was:
quelle
Das von
JUnit run
und von abweichende Ergebnis der Testausführungmaven install
scheint ein Symptom für verschiedene Probleme zu sein.Das Deaktivieren der Testausführung zur Wiederverwendung von Threads hat in unserem Fall auch das Symptom beseitigt, aber der Eindruck, dass der Code nicht threadsicher war, war immer noch stark.
In unserem Fall war der Unterschied auf das Vorhandensein einer Bohne zurückzuführen, die das Testverhalten veränderte. Das Ausführen nur des JUnit-Tests würde in Ordnung sein, das Ausführen des Projektziels
install
würde jedoch zu einem fehlgeschlagenen Testfall führen. Da es sich um den in der Entwicklung befindlichen Testfall handelte, war er sofort verdächtig.Es ergab sich, dass ein anderer Testfall eine Bohne durch Spring instanziierte, die bis zur Ausführung des neuen Testfalls überleben würde. Die Bean-Präsenz veränderte das Verhalten einiger Klassen und führte zu dem fehlgeschlagenen Ergebnis.
Die Lösung in unserem Fall bestand darin, die Bohne loszuwerden, die überhaupt nicht benötigt wurde (ein weiterer Preis von der Copy + Paste- Pistole).
Ich schlage jedem mit diesem Symptom vor, die Grundursache zu untersuchen. Durch Deaktivieren der Thread-Wiederverwendung bei der Testausführung wird diese möglicherweise nur ausgeblendet.
quelle
Ich hatte das gleiche Problem, aber das Problem für mich war, dass Java-Zusicherungen (z. B. assert (num> 0)) nicht für Eclipse aktiviert waren, sondern beim Ausführen von maven.
Daher hat das Ausführen der jUnit-Tests von Eclipse den Assertionsfehler nicht ausgelöst.
Dies wird bei Verwendung von jUnit 4.11 (im Gegensatz zu der älteren Version, die ich verwendet habe) deutlich, da der Assertionsfehler ausgedruckt wird, z
quelle
Ich hatte ein ähnliches Problem mit einer anderen Ursache und daher einer anderen Lösung. In meinem Fall hatte ich tatsächlich einen Fehler, bei dem ein Singleton-Objekt eine Mitgliedsvariable hatte, die nicht threadsicher geändert wurde. In diesem Fall würde das Befolgen der akzeptierten Antworten und das Umgehen des parallelen Tests nur den Fehler verbergen, der durch den Test tatsächlich aufgedeckt wurde. Meine Lösung besteht natürlich darin, das Design so zu korrigieren, dass ich dieses schlechte Verhalten nicht in meinem Code habe.
quelle
[Ich bin nicht sicher, ob dies eine Antwort auf die ursprüngliche Frage ist, da der Stacktrace hier etwas anders aussieht, aber für andere nützlich sein kann.]
In Surefire können Tests fehlschlagen, wenn Sie auch Cobertura ausführen (um Berichte zur Codeabdeckung zu erhalten). Dies liegt daran, dass Cobertura Proxys benötigt (um die Verwendung von Code zu messen) und es einen Konflikt zwischen diesen und Spring-Proxys gibt. Dies tritt nur auf, wenn Spring cglib2 verwendet. Dies ist beispielsweise der Fall,
proxy-target-class="true"
wenn Sie über ein Proxy-Objekt verfügen, das keine Schnittstellen implementiert.Die normale Lösung besteht darin, eine Schnittstelle hinzuzufügen. So sollten DAOs beispielsweise Schnittstellen sein, die von einer DAOImpl-Klasse implementiert werden. Wenn Sie die Schnittstelle automatisch verdrahten, funktioniert alles einwandfrei (da cglib2 nicht mehr benötigt wird; stattdessen kann ein einfacherer JDK-Proxy für die Schnittstelle verwendet werden, und Cobertura funktioniert damit einwandfrei).
Sie können jedoch keine Schnittstellen mit mit Anmerkungen versehenen Controllern verwenden (beim Versuch, den Controller in einem Servlet zu verwenden, wird ein Laufzeitfehler angezeigt). Ich habe keine Lösung für Cobertura + Spring-Tests, bei denen Controller automatisch verdrahtet werden.
quelle
Ich hatte ein ähnliches Problem: JUnit-Tests sind in Maven Surefire fehlgeschlagen, wurden jedoch in Eclipse bestanden, als ich die JUnit-Bibliotheksversion 4.11.0 aus dem SpringSource Bundle Repository verwendete. Insbesondere:
Dann habe ich es durch die folgende JUnit-Bibliothek Version 4.11 ersetzt und alles funktioniert gut.
quelle
Ich hatte heute dieses Problem beim Testen einer Methode, die ein Objekt, das a enthielt,
Map
in eine JSON-Zeichenfolge konvertierte . Ich gehe davon aus, dass Eclipse und das Maven-Safefire-Plugin unterschiedliche JREs mit unterschiedlichenHashMap
Ordnungsimplementierungen oder Ähnlichem verwendeten, was dazu führte, dass die durch Eclipse durchgeführten Tests bestanden wurden und die durch Surefire durchgeführten Tests fehlschlugen (assertEquals
fehlgeschlagen). Die einfachste Lösung war die Verwendung einer Map-Implementierung mit zuverlässiger Bestellung.quelle
Sie müssen keine DataSource in den JpaTransactionManager einfügen, da die EntityManagerFactory bereits über eine Datenquelle verfügt. Versuche Folgendes:
quelle
Wenn Tests in Eclipse bestanden werden und mit Maven fehlschlagen, handelt es sich normalerweise um ein Klassenpfadproblem, da dies der Hauptunterschied zwischen beiden ist.
Sie können also den Klassenpfad mit maven -X test überprüfen und den Klassenpfad von Eclipse über die Menüs oder in der .classpath-Datei im Stammverzeichnis Ihres Projekts überprüfen.
Sind Sie sich zum Beispiel sicher, dass sich die Personenservice-test.xml im Klassenpfad befindet?
quelle
Dies hat mir bei der Fehlerbehebung geholfen. Ich hatte ähnliche Symptome, dass Maven fehlschlagen würde, aber das Ausführen von Junit-Tests läuft einwandfrei.
Wie sich herausstellt, enthält meine übergeordnete pom.xml die folgende Definition:
Und in meinem Projekt überschreibe ich es, um die argLine zu entfernen:
Hoffentlich hilft dies jemandem bei der Fehlerbehebung bei todsicheren Plugins.
quelle
<forkMode>
VERRINGERT seit Version 2.14. Verwenden SieforkCount
undreuseForks
stattdessen. "Ich hatte das gleiche Problem und die Lösung für mich bestand darin, Maven zu erlauben, alle Abhängigkeiten zu handhaben, einschließlich lokaler Gläser. Ich habe Maven für Online-Abhängigkeiten verwendet und den Erstellungspfad manuell für lokale Abhängigkeiten konfiguriert. Daher war Maven die von mir manuell konfigurierten Abhängigkeiten nicht bekannt.
Ich habe diese Lösung verwendet, um die lokalen JAR-Abhängigkeiten in Maven zu installieren:
Wie füge ich lokale JAR-Dateien in ein Maven-Projekt ein?
quelle
In meinem Fall war der Grund ein Fehler im Code. Der Test stützte sich auf eine bestimmte Reihenfolge von Elementen in a
HashSet
, die sich als unterschiedlich herausstellte, wenn sie entweder in Eclipse oder in Maven Surefire ausgeführt wurden.quelle
Es ist sehr wahrscheinlich, dass sich Ihre Konfigurationsdateien in src / main / resources befinden , während sie sich unter src / test / resources befinden müssen, damit sie unter maven ordnungsgemäß funktionieren.
https://cwiki.apache.org/UIMA/differences-between-running-unit-tests-in-eclipse-and-in-maven.html
Ich antworte darauf nach zwei Jahren, weil ich diese Antwort hier nicht finden konnte und ich denke, dass es die richtige ist.
quelle
src/main/resources
ist für Testssrc/test/resources
sichtbar, für Produktionscode jedoch nicht.