Я написал несколько тестов JUnit, используя библиотеки JUnit 4 и spring -test. Когда я запускаю тесты внутри Eclipse, все работает нормально и проходит успешно. Но когда я запускаю их с помощью Maven (в процессе сборки), они не дают ошибки, связанной с Spring. Я не уверен, что вызывает проблему, 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 значение always в конфигурации maven surefire в pom.xml:
Параметры Surefire: http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html
Изменить (январь 2014 г.):
Как отметил Питер Перхач , параметр 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>
Дополнительные сведения см. В разделах «Параметры форка» и «Параллельное выполнение тестов».
источник
Я внезапно столкнулся с этой ошибкой, и решением для меня было отключить параллельное выполнение тестов.
Ваш пробег может отличаться, так как я могу уменьшить количество неудачных тестов, настроив surefire для запуска параллельных тестов по «классам»:
<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.7.2</version> <configuration> <parallel>classes</parallel> <threadCount>10</threadCount> </configuration> </plugin>
Как я уже писал вначале, этого было недостаточно для моего набора тестов, поэтому я полностью отключил параллелизм, удалив
<configuration>
раздел.источник
У меня была аналогичная проблема, аннотация
@Autowired
в тестовом коде не работала при использовании командной строки Maven, в то время как в Eclipse она работала нормально. Я просто обновил свою версию JUnit с 4.4 до 4.9, и проблема была решена.<dependency> <groupId>junit</groupId <artifactId>junit</artifactId> <version>4.9</version> </dependency>
источник
Это не совсем применимо к вашей ситуации, но у меня было то же самое - тесты, которые проходили в Eclipse, терпели неудачу, когда выполнялась цель тестирования из Maven.
Оказалось, что раньше это был тест в моем наборе, в другом пакете . На это у меня ушла неделя!
Более ранний тест тестировал некоторые классы Logback и создавал контекст Logback из файла конфигурации.
Более поздний тест тестировал подкласс Spring SimpleRestTemplate, и каким-то образом был сохранен более ранний контекст Logback с включенной DEBUG. Это привело к дополнительным вызовам в RestTemplate для регистрации HttpStatus и т. Д.
Другое дело проверить, попадет ли когда-нибудь в такую ситуацию. Я исправил свою проблему, внедрив некоторые Mocks в мой тестовый класс Logback, чтобы не было создано никаких реальных контекстов Logback.
источник
У меня аналогичная проблема, но с 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>
источник
Результат выполнения теста, отличный от
JUnit run
и отmaven install
, может быть признаком нескольких проблем.Отключение повторного использования потоков при выполнении теста также избавило от симптома в нашем случае, но впечатление, что код не является потокобезопасным, все еще оставалось сильным.
В нашем случае разница была связана с присутствием bean-компонента, который изменил поведение теста. Выполнение только теста JUnit приведет к хорошему результату, но выполнение
install
целевого проекта приведет к провалу теста. Поскольку это был тестовый пример в стадии разработки, он сразу вызвал подозрение.Это привело к тому, что другой тестовый пример создавал экземпляр bean-компонента через Spring, который выжил бы до выполнения нового тестового примера. Присутствие bean-компонента изменяло поведение некоторых классов и приводило к неудачному результату.
В нашем случае решение заключалось в том, чтобы избавиться от bean-компонента, который изначально не был нужен (еще один приз от пистолета для копирования + вставки ).
Я предлагаю всем, у кого есть этот симптом, выяснить, в чем его первопричина. Отключение повторного использования потока при выполнении теста может только скрыть это.
источник
У меня была такая же проблема, но для меня проблема заключалась в том, что утверждения Java (например, assert (num> 0)) не были включены для Eclipse, но были включены при запуске maven.
Таким образом, запуск тестов jUnit из Eclipse не вызывал ошибку утверждения.
Это становится понятным при использовании 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)
источник
У меня была аналогичная проблема с другой причиной и, следовательно, с другим решением. В моем случае у меня действительно была ошибка, когда у одноэлементного объекта переменная-член была изменена небезопасным способом. В этом случае следование принятым ответам и обход параллельного тестирования только скроет ошибку, которая действительно была обнаружена тестом. Мое решение, конечно, - исправить дизайн, чтобы в моем коде не было такого плохого поведения.
источник
[Я не уверен, что это ответ на исходный вопрос, так как stacktrace здесь выглядит немного иначе, но может быть полезен другим.]
Вы можете получить неудачные тесты в Surefire, когда вы также используете Cobertura (для получения отчетов о покрытии кода). Это связано с тем, что Cobertura требует прокси (для измерения использования кода), и между ними и прокси Spring существует какой-то конфликт. Это только происходит тогда, когда Spring использует cglib2, что могло бы иметь место, если, например, у вас есть
proxy-target-class="true"
или если у вас есть объект, который проксируется, но не реализует интерфейсы.Обычное исправление этого - добавление интерфейса. Так, например, DAO должны быть интерфейсами, реализованными классом DAOImpl. Если вы автоматически подключаете интерфейс, все будет работать нормально (поскольку cglib2 больше не требуется; вместо него можно использовать более простой прокси JDK для интерфейса, и Cobertura отлично с этим работает).
Однако вы не можете использовать интерфейсы с аннотированными контроллерами (вы получите ошибку времени выполнения при попытке использовать контроллер в сервлете) - у меня нет решения для тестов Cobertura + Spring, которые автоматически подключают контроллеры.
источник
У меня была аналогичная проблема: тесты JUnit не выполнялись в Maven Surefire, но прошли в Eclipse, когда я использовал версию библиотеки JUnit 4.11.0 из репозитория SpringSource Bundle. В часности:
<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>
источник
У меня возникла эта проблема сегодня, когда я тестировал метод, преобразующий объект, содержащий a,
Map
в строку JSON. Я предполагаю, что Eclipse и плагин Maven surefire использовали разные JRE, которые имели разные реализацииHashMap
упорядочивания или что-то в этом роде, что заставляло тесты, проходящие через Eclipse, проходить, а тесты, проходящие через них,assertEquals
терпели неудачу ( неудачно). Самым простым решением было использовать реализацию Map с надежным упорядочиванием.источник
Вам не нужно вводить DataSource в JpaTransactionManager, поскольку EntityManagerFactory уже имеет источник данных. Попробуйте следующее:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean>
источник
Обычно, когда тесты проходят в eclipse и терпят неудачу с maven, это проблема пути к классам, потому что это основное различие между ними.
Таким образом, вы можете проверить путь к классам с помощью maven -X test и проверить путь к классам eclipse через меню или в файле .classpath в корне вашего проекта.
Вы уверены, например, что personservice-test.xml находится в пути к классам?
источник
Это помогло мне решить мою проблему. У меня были аналогичные симптомы в том, что 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.
источник
<forkMode>
УСТАРЕЛО, начиная с версии 2.14. Используйте вместо этогоforkCount
иreuseForks
»У меня была та же проблема, и я решил разрешить Maven обрабатывать все зависимости, в том числе локальные jar-файлы. Я использовал Maven для онлайн-зависимостей и вручную настроил путь сборки для локальных зависимостей. Таким образом, Maven не знал о зависимостях, которые я настроил вручную.
Я использовал это решение для установки локальных зависимостей jar в Maven:
Как добавить локальные файлы jar в проект maven?
источник
В моем случае причина была в ошибке в коде. Тест основывался на определенном порядке элементов в a
HashSet
, который оказался другим при запуске в Eclipse или в Maven Surefire.источник
Скорее всего, ваши файлы конфигурации находятся в src / main / resources , тогда как они должны находиться в src / test / resources для правильной работы под maven.
https://cwiki.apache.org/UIMA/differences-between-running-unit-tests-in-eclipse-and-in-maven.html
Я отвечаю на это через два года, потому что я не смог найти здесь этот ответ и считаю его правильным.
источник
src/main/resources
отображается для тестов, ноsrc/test/resources
не отображается для производственного кода.