J'ai écrit des tests JUnit en utilisant JUnit 4 et des bibliothèques de tests de ressorts. Lorsque j'exécute les tests dans Eclipse, je lance correctement et je réussis. Mais quand je les lance en utilisant Maven (pendant le processus de construction), ils échouent en donnant une erreur liée au ressort. Je ne suis pas sûr de la cause du problème, JUnit, Surefire ou Spring. Voici mon code de test, la configuration du ressort et l'exception que je reçois de 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());
}});
}
}
peopleervice-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>
Exception à 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
Réponses:
J'ai eu le même problème (les tests JUnit ont échoué dans Maven Surefire mais ont réussi dans Eclipse) et j'ai réussi à le résoudre en définissant forkMode sur toujours dans la configuration maven surefire dans pom.xml:
Paramètres Surefire: http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html
Edit (janvier 2014):
Comme l'a souligné Peter Perháč , le paramètre forkMode est obsolète depuis Surefire 2.14. À partir de Surefire 2.14, utilisez plutôt ceci:
Pour plus d'informations, voir Options de fourche et exécution de tests parallèles
la source
J'ai soudainement rencontré cette erreur, et la solution pour moi était de désactiver pour exécuter des tests en parallèle.
Votre kilométrage peut varier, car je pourrais réduire le nombre de tests échouant en configurant surefire pour exécuter des tests parallèles par «classes»:
Comme je l'ai écrit en premier, ce n'était pas suffisant pour ma suite de tests, j'ai donc complètement désactivé le parallèle en supprimant la
<configuration>
section.la source
J'ai eu un problème similaire, l'annotation
@Autowired
dans le code de test ne fonctionnait pas en utilisant la ligne de commande Maven alors que cela fonctionnait bien dans Eclipse. Je viens de mettre à jour ma version JUnit de 4.4 à 4.9 et le problème a été résolu.la source
Cela ne s'applique pas exactement à votre situation, mais j'ai eu la même chose: les tests qui réussiraient dans Eclipse ont échoué lorsque l'objectif de test de Maven a été exécuté.
Il s'est avéré être un test plus tôt dans ma suite, dans un package différent . Cela m'a pris une semaine à résoudre!
Un test précédent testait certaines classes Logback et créait un contexte Logback à partir d'un fichier de configuration.
Le dernier test testait une sous-classe de SimpleRestTemplate de Spring et, d'une manière ou d'une autre, le contexte Logback précédent était maintenu, avec DEBUG activé. Cela a provoqué des appels supplémentaires dans RestTemplate pour enregistrer HttpStatus, etc.
C'est une autre chose de vérifier si jamais on se retrouve dans cette situation. J'ai résolu mon problème en injectant des Mocks dans ma classe de test Logback, afin qu'aucun réel contexte Logback ne soit créé.
la source
J'ai le même problème, mais avec IntelliJ IDEA + Maven + TestNG + spring-test. ( spring-test est essentiel bien sûr :)) Cela a été corrigé lorsque j'ai changé la configuration de maven-surefire-plugin pour désactiver les tests en parallèle. Comme ça:
la source
Le résultat de l'exécution du test différent de
JUnit run
et demaven install
semble être le symptôme de plusieurs problèmes.La désactivation de l'exécution des tests de réutilisation des threads a également éliminé le symptôme dans notre cas, mais l'impression que le code n'était pas thread-safe était toujours forte.
Dans notre cas, la différence était due à la présence d'un bean qui a modifié le comportement du test. Exécuter uniquement le test JUnit résulterait bien, mais exécuter la
install
cible du projet entraînerait un échec du scénario de test. Puisqu'il s'agissait du cas de test en cours de développement, il était immédiatement suspect.Il en résultait qu'un autre cas de test instanciait un bean via Spring qui survivrait jusqu'à l'exécution du nouveau cas de test. La présence du bean modifiait le comportement de certaines classes et produisait le résultat échoué.
La solution dans notre cas était de se débarrasser du haricot, qui n'était pas nécessaire en premier lieu (encore un autre prix du pistolet copier-coller ).
Je suggère à tous ceux qui ont ce symptôme d'enquêter sur la cause profonde. La désactivation de la réutilisation des threads lors de l'exécution du test peut uniquement le masquer.
la source
J'ai eu le même problème, mais le problème pour moi était que les assertions Java (par exemple assert (num> 0)) n'étaient pas activées pour Eclipse, mais étaient activées lors de l'exécution de maven.
Par conséquent, l'exécution des tests jUnit à partir d'Eclipse n'a pas déclenché l'erreur d'assertion.
Ceci est précisé lors de l'utilisation de jUnit 4.11 (par opposition à l'ancienne version que j'utilisais) car il affiche l'erreur d'assertion, par exemple
la source
J'ai eu un problème similaire avec une cause différente et donc une solution différente. Dans mon cas, j'ai en fait eu une erreur où un objet singleton avait une variable membre modifiée d'une manière non threadsafe. Dans ce cas, suivre les réponses acceptées et contourner le test parallèle ne ferait que masquer l'erreur réellement révélée par le test. Ma solution, bien sûr, est de corriger la conception afin que je n'ai pas ce mauvais comportement dans mon code.
la source
[Je ne suis pas sûr que ce soit une réponse à la question initiale, car le stacktrace ici semble légèrement différent, mais il peut être utile à d'autres.]
Vous pouvez obtenir des tests échouant dans Surefire lorsque vous exécutez également Cobertura (pour obtenir des rapports de couverture de code). En effet, Cobertura nécessite des proxies (pour mesurer l'utilisation du code) et il existe une sorte de conflit entre ceux-ci et les proxys Spring. Cela ne se produit que lorsque Spring utilise cglib2, ce qui serait le cas si, par exemple, vous en avez
proxy-target-class="true"
, ou si vous avez un objet qui fait l'objet d'un proxy qui n'implémente pas les interfaces.La solution normale consiste à ajouter une interface. Ainsi, par exemple, les DAO doivent être des interfaces, implémentées par une classe DAOImpl. Si vous câblez automatiquement sur l'interface, tout fonctionnera correctement (car cglib2 n'est plus nécessaire; un proxy JDK plus simple vers l'interface peut être utilisé à la place et Cobertura fonctionne bien avec cela).
Cependant, vous ne pouvez pas utiliser d'interfaces avec des contrôleurs annotés (vous obtiendrez une erreur d'exécution en essayant d'utiliser le contrôleur dans un servlet) - Je n'ai pas de solution pour les tests Cobertura + Spring qui acheminent automatiquement les contrôleurs.
la source
J'ai eu un problème similaire: les tests JUnit ont échoué dans Maven Surefire mais ont réussi dans Eclipse lorsque j'ai utilisé la bibliothèque JUnit version 4.11.0 de SpringSource Bundle Repository. Particulier:
Ensuite, je l'ai remplacé par la version 4.11 de la bibliothèque JUnit suivante et tout fonctionne bien.
la source
J'ai eu ce problème aujourd'hui en testant une méthode qui convertissait un objet contenant une
Map
chaîne JSON. Je suppose qu'Eclipse et le plugin Maven surefire utilisaient différents JRE qui avaient différentes implémentations deHashMap
commande ou quelque chose du genre , ce qui a entraîné la réussite des tests exécutés via Eclipse et l'échec des tests exécutés via surefire (assertEquals
échec). La solution la plus simple consistait à utiliser une implémentation de Map avec une commande fiable.la source
Vous n'avez pas besoin d'injecter une DataSource dans le JpaTransactionManager car l'EntityManagerFactory a déjà une source de données. Essayez ce qui suit:
la source
Habituellement, lorsque les tests réussissent dans eclipse et échouent avec maven, il s'agit d'un problème de chemin de classe car c'est la principale différence entre les deux.
Vous pouvez donc vérifier le classpath avec maven -X test et vérifier le classpath de eclipse via les menus ou dans le fichier .classpath à la racine de votre projet.
Etes-vous sûr, par exemple, que personservice-test.xml est dans le classpath?
la source
Cela m'a aidé à résoudre mon problème. J'avais des symptômes similaires en ce que maven échouerait, mais l'exécution des tests junit fonctionnait bien.
Il s'avère que mon pom.xml parent contient la définition suivante:
Et dans mon projet, je le remplace pour supprimer l'argLine:
Espérons que cela aidera quelqu'un à dépanner le plugin infaillible.
la source
<forkMode>
DÉCONSEILLÉ depuis la version 2.14. UtilisezforkCount
et à lareuseForks
place. "J'avais le même problème, et la solution pour moi était de permettre à Maven de gérer toutes les dépendances, y compris les fichiers jar locaux. J'ai utilisé Maven pour les dépendances en ligne et configuré manuellement le chemin de construction pour les dépendances locales. Ainsi, Maven n'était pas au courant des dépendances que j'avais configurées manuellement.
J'ai utilisé cette solution pour installer les dépendances jar locales dans Maven:
Comment ajouter des fichiers JAR locaux dans le projet maven?
la source
Dans mon cas, la raison était un bogue dans le code. Le test reposait sur un certain ordre d'éléments dans a
HashSet
, qui s'est avéré différent lorsqu'il était exécuté dans Eclipse ou dans Maven Surefire.la source
Il est fort probable que vos fichiers de configuration se trouvent dans src / main / resources , alors qu'ils doivent être sous src / test / resources pour fonctionner correctement sous maven.
https://cwiki.apache.org/UIMA/differences-between-running-unit-tests-in-eclipse-and-in-maven.html
Je réponds après deux ans car je n'ai pas trouvé cette réponse ici et je pense que c'est la bonne.
la source
src/main/resources
est visible pour les tests, maissrc/test/resources
n'est pas visible pour le code de production.