He escrito algunas pruebas de JUnit usando JUnit 4 y bibliotecas de prueba de primavera. Cuando ejecuto las pruebas dentro de Eclipse, corro bien y paso. Pero cuando los ejecuto usando Maven (durante el proceso de compilación), fallan y dan un error relacionado con la primavera. No estoy seguro de qué está causando el problema, JUnit, Surefire o Spring. Aquí está mi código de prueba, configuración de primavera y la excepción que obtengo 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());
}});
}
}
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>
Excepción en 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
Respuestas:
Yo tenía el mismo problema (JUnit pruebas fallidas en Maven éxito seguro, pero pasa en Eclipse) y logró resolver estableciendo forkMode para siempre en el experto en la configuración segura pom.xml:
Parámetros Surefire: http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html
Editar (enero de 2014):
Como señaló Peter Perháč , el parámetro forkMode está obsoleto desde Surefire 2.14. A partir de Surefire 2.14 use esto en su lugar:
Para obtener más información, consulte Opciones de bifurcación y ejecución de pruebas en paralelo
fuente
De repente experimenté este error y la solución para mí fue desactivar la ejecución de pruebas en paralelo.
Su kilometraje puede variar, ya que podría reducir el número de pruebas fallidas configurando surefire para ejecutar pruebas paralelas por "clases":
Como escribí primero, esto no fue suficiente para mi conjunto de pruebas, por lo que desactivé completamente el paralelo eliminando la
<configuration>
sección.fuente
Tuve un problema similar, la anotación
@Autowired
en el código de prueba no funcionó usando la línea de comando de Maven mientras funcionaba bien en Eclipse. Acabo de actualizar mi versión de JUnit de 4.4 a 4.9 y el problema se resolvió.fuente
Esto no se aplica exactamente a su situación, pero tuve lo mismo: las pruebas que pasarían en Eclipse fallaron cuando se ejecutó el objetivo de prueba de Maven.
Resultó ser una prueba anterior en mi suite, en un paquete diferente . ¡Me tomó una semana resolverlo!
Una prueba anterior estaba probando algunas clases de Logback y creó un contexto de Logback a partir de un archivo de configuración.
La prueba posterior estaba probando una subclase de SimpleRestTemplate de Spring y, de alguna manera, se mantuvo el contexto de Logback anterior, con DEBUG activado. Esto provocó que se hicieran llamadas adicionales en RestTemplate para registrar HttpStatus, etc.
Otra cosa es comprobar si alguna vez se mete en esta situación. Solucioné mi problema inyectando algunos Mocks en mi clase de prueba de Logback, para que no se crearan contextos de Logback reales.
fuente
Tengo un problema similar, pero con IntelliJ IDEA + Maven + TestNG + spring-test. ( Spring-test es esencial, por supuesto :)) Se corrigió cuando cambié la configuración de maven-surefire-plugin para deshabilitar la ejecución de pruebas en paralelo. Me gusta esto:
fuente
El resultado de la ejecución de la prueba es diferente
JUnit run
ymaven install
parece ser un síntoma de varios problemas.La desactivación de la ejecución de la prueba de reutilización de subprocesos también eliminó el síntoma en nuestro caso, pero la impresión de que el código no era seguro para subprocesos seguía siendo fuerte.
En nuestro caso la diferencia se debió a la presencia de un frijol que modificó el comportamiento de la prueba. Ejecutar solo la prueba JUnit resultaría bien, pero ejecutar el
install
objetivo del proyecto resultaría en un caso de prueba fallido. Dado que era el caso de prueba en desarrollo, fue inmediatamente sospechoso.Resultó que otro caso de prueba estaba instanciando un bean a través de Spring que sobreviviría hasta la ejecución del nuevo caso de prueba. La presencia de bean estaba modificando el comportamiento de algunas clases y produciendo el resultado fallido.
La solución en nuestro caso fue deshacerse del bean, que no era necesario en primer lugar (otro premio más de la pistola de copiar + pegar ).
Sugiero a todas las personas con este síntoma que investiguen cuál es la causa raíz. Deshabilitar la reutilización de subprocesos en la ejecución de la prueba solo podría ocultarlo.
fuente
Tuve el mismo problema, pero el problema para mí fue que las afirmaciones de Java (por ejemplo, assert (num> 0)) no estaban habilitadas para Eclipse, pero estaban habilitadas al ejecutar maven.
Por lo tanto, la ejecución de las pruebas de jUnit desde Eclipse no activó el error de aserción.
Esto se aclara cuando se usa jUnit 4.11 (a diferencia de la versión anterior que estaba usando) porque imprime el error de aserción, por ejemplo
fuente
Tuve un problema similar con una causa diferente y, por lo tanto, una solución diferente. En mi caso, tuve un error en el que un objeto singleton tenía una variable miembro modificada de una manera no segura para subprocesos. En este caso, seguir las respuestas aceptadas y eludir las pruebas paralelas solo ocultaría el error que realmente reveló la prueba. Mi solución, por supuesto, es arreglar el diseño para que no tenga este mal comportamiento en mi código.
fuente
[No estoy seguro de que esta sea una respuesta a la pregunta original, ya que el stacktrace aquí se ve ligeramente diferente, pero puede ser útil para otros].
Puede obtener pruebas que fallan en Surefire cuando también está ejecutando Cobertura (para obtener informes de cobertura de código). Esto se debe a que Cobertura requiere proxies (para medir el uso del código) y existe algún tipo de conflicto entre ellos y los proxies de Spring. Esto solo ocurre cuando Spring usa cglib2, que sería el caso si, por ejemplo, tiene
proxy-target-class="true"
, o si tiene un objeto que está siendo proxy que no implementa interfaces.La solución normal a esto es agregar una interfaz. Entonces, por ejemplo, las DAO deberían ser interfaces, implementadas por una clase DAOImpl. Si realiza el autowire en la interfaz, todo funcionará bien (porque cglib2 ya no es necesario; en su lugar, se puede usar un proxy JDK más simple para la interfaz y Cobertura funciona bien con esto).
Sin embargo, no puede usar interfaces con controladores anotados (obtendrá un error de tiempo de ejecución cuando intente usar el controlador en un servlet) - No tengo una solución para las pruebas de Cobertura + Spring que autowire los controladores.
fuente
Tuve un problema similar: las pruebas de JUnit fallaron en Maven Surefire pero pasaron en Eclipse cuando usé la versión 4.11.0 de la biblioteca JUnit de SpringSource Bundle Repository. Particular:
Luego lo reemplacé con la siguiente versión de la biblioteca JUnit 4.11 y todo funciona bien.
fuente
Hoy tuve este problema probando un método que convertía un objeto que contenía
Map
a en una cadena JSON. Supongo que Eclipse y el complemento seguro de Maven estaban usando diferentes JRE que tenían diferentes implementaciones deHashMap
pedidos o algo así, lo que hizo que las pruebas se ejecutaran a través de Eclipse y las pruebas se ejecutaran a través de infalible para fallar (assertEquals
fallaron). La solución más sencilla fue utilizar una implementación de Map que tuviera un orden confiable.fuente
No es necesario inyectar un DataSource en JpaTransactionManager ya que EntityManagerFactory ya tiene un origen de datos. Intente lo siguiente:
fuente
Por lo general, cuando las pruebas pasan en eclipse y fallan con maven, es un problema de classpath porque es la principal diferencia entre los dos.
Entonces puede verificar la ruta de clases con maven -X test y verificar la ruta de clases de eclipse a través de los menús o en el archivo .classpath en la raíz de su proyecto.
¿Está seguro, por ejemplo, de que personservice-test.xml está en la ruta de clase?
fuente
Esto me ha ayudado a solucionar mi problema. Tuve síntomas similares en que maven fallaría, sin embargo, ejecutar pruebas junit funciona bien.
Resulta que mi padre pom.xml contiene la siguiente definición:
Y en mi proyecto lo anulo para eliminar argLine:
Con suerte, esto ayudará a alguien a solucionar problemas del plugin infalible.
fuente
<forkMode>
DESAPARECIDO desde la versión 2.14. UtiliceforkCount
y en sureuseForks
lugar "Tuve el mismo problema y la solución para mí fue permitir que Maven manejara todas las dependencias, incluidos los archivos jar locales. Usé Maven para las dependencias en línea y configuré la ruta de compilación manualmente para las dependencias locales. Por lo tanto, Maven no conocía las dependencias que configuré manualmente.
Usé esta solución para instalar las dependencias de jar locales en Maven:
¿Cómo agregar archivos jar locales en el proyecto maven?
fuente
En mi caso, la razón fue un error en el código. La prueba se basó en un cierto orden de elementos en a
HashSet
, que resultó ser diferente cuando se ejecutó en Eclipse o en Maven Surefire.fuente
Lo más probable es que sus archivos de configuración estén en src / main / resources , mientras que deben estar en src / test / resources para que funcionen correctamente en maven.
https://cwiki.apache.org/UIMA/differences-between-running-unit-tests-in-eclipse-and-in-maven.html
Estoy respondiendo esto después de dos años porque no pude encontrar esta respuesta aquí y creo que es la correcta.
fuente
src/main/resources
es visible para las pruebas, perosrc/test/resources
no es visible para el código de producción.