Saya telah menulis beberapa tes JUnit menggunakan JUnit 4 dan perpustakaan uji musim semi. Ketika saya menjalankan tes di dalam Eclipse kemudian berjalan dengan baik dan lulus. Tetapi ketika saya menjalankannya menggunakan Maven (selama proses pembuatan), mereka gagal memberikan kesalahan terkait pegas. Saya tidak yakin apa yang menyebabkan masalah, JUnit, Surefire, atau Spring. Berikut adalah kode pengujian saya, konfigurasi pegas dan pengecualian yang saya dapatkan dari 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());
}});
}
}
personervice-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>
Pengecualian di 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
Jawaban:
Saya memiliki masalah yang sama (tes JUnit gagal di Maven Surefire tetapi lolos di Eclipse) dan berhasil menyelesaikannya dengan mengatur forkMode untuk selalu dalam konfigurasi maven surefire di pom.xml:
Parameter yang pasti: http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html
Edit (Januari 2014):
Seperti yang ditunjukkan oleh Peter Perháč , parameter forkMode tidak digunakan lagi sejak Surefire 2.14. Mulai dari Surefire 2.14 gunakan ini sebagai gantinya:
Untuk informasi lebih lanjut, lihat Opsi Fork dan Eksekusi Tes Paralel
sumber
Saya tiba-tiba mengalami kesalahan ini, dan solusi bagi saya adalah menonaktifkan untuk menjalankan tes secara paralel.
Jarak tempuh Anda mungkin berbeda, karena saya dapat menurunkan jumlah pengujian yang gagal dengan mengkonfigurasi yang pasti untuk menjalankan pengujian paralel berdasarkan ´classes´ .:
Seperti yang saya tulis pertama kali, ini tidak cukup untuk rangkaian pengujian saya, jadi saya sepenuhnya menonaktifkan paralel dengan menghapus
<configuration>
bagian tersebut.sumber
Saya memiliki masalah yang sama, penjelasan
@Autowired
dalam kode pengujian tidak berfungsi dengan menggunakan baris perintah Maven sementara itu berfungsi dengan baik di Eclipse. Saya baru saja memperbarui versi JUnit saya dari 4.4 menjadi 4.9 dan masalahnya telah terpecahkan.sumber
Ini tidak berlaku untuk situasi Anda, tetapi saya memiliki hal yang sama - tes yang akan lulus di Eclipse gagal saat tujuan uji coba dari Maven dijalankan.
Ternyata itu adalah tes sebelumnya di suite saya, dalam paket yang berbeda . Ini membutuhkan waktu seminggu untuk menyelesaikannya!
Pengujian sebelumnya menguji beberapa kelas Logback, dan membuat konteks Logback dari file konfigurasi.
Tes selanjutnya adalah menguji subkelas SimpleRestTemplate Spring, dan entah bagaimana, konteks Logback sebelumnya diadakan, dengan DEBUG aktif. Ini menyebabkan panggilan ekstra dilakukan di RestTemplate untuk mencatat HttpStatus, dll.
Memeriksa apakah seseorang pernah masuk ke dalam situasi ini adalah hal lain. Saya memperbaiki masalah saya dengan menyuntikkan beberapa Mock ke dalam kelas pengujian Logback saya, sehingga tidak ada konteks Logback nyata yang dibuat.
sumber
Saya memiliki masalah yang sama, tetapi dengan IntelliJ IDEA + Maven + TestNG + spring-test. ( uji musim semi sangat penting tentu saja :)) Telah diperbaiki ketika saya mengubah konfigurasi maven-surefire-plugin untuk menonaktifkan pengujian yang dijalankan secara paralel. Seperti ini:
sumber
Hasil eksekusi uji berbeda dari
JUnit run
dan darimaven install
tampaknya menjadi gejala dari beberapa masalah.Menonaktifkan eksekusi uji penggunaan ulang thread juga menghilangkan gejala dalam kasus kami, tetapi kesan bahwa kode tersebut tidak aman untuk thread masih kuat.
Dalam kasus kami, perbedaannya disebabkan oleh adanya kacang yang mengubah perilaku pengujian. Menjalankan pengujian JUnit saja akan baik-baik saja, tetapi menjalankan proyek
install
target akan mengakibatkan kasus pengujian yang gagal. Karena itu adalah kasus uji yang sedang dikembangkan, itu langsung mencurigakan.Ini menghasilkan kasus uji lain yang membuat contoh kacang melalui Spring yang akan bertahan sampai eksekusi kasus uji baru. Kehadiran kacang memodifikasi perilaku beberapa kelas dan menghasilkan hasil yang gagal.
Solusi dalam kasus kami adalah menyingkirkan kacang, yang tidak diperlukan sejak awal (hadiah lain dari salinan + tempel) pistol ).
Saya menyarankan semua orang dengan gejala ini untuk menyelidiki apa akar penyebabnya. Menonaktifkan penggunaan ulang thread dalam eksekusi pengujian mungkin hanya menyembunyikannya.
sumber
Saya mengalami masalah yang sama, tetapi masalah bagi saya adalah bahwa pernyataan Java (misalnya assert (num> 0)) tidak diaktifkan untuk Eclipse, tetapi diaktifkan saat menjalankan maven.
Oleh karena itu, menjalankan tes jUnit dari Eclipse tidak menangkap memicu kesalahan pernyataan.
Ini diperjelas saat menggunakan jUnit 4.11 (berlawanan dengan versi lama yang saya gunakan) karena mencetak kesalahan pernyataan, mis.
sumber
Saya memiliki masalah serupa dengan penyebab yang berbeda dan karena itu solusi yang berbeda. Dalam kasus saya, saya benar-benar mengalami kesalahan di mana objek tunggal memiliki variabel anggota yang dimodifikasi dengan cara yang tidak aman. Dalam hal ini, mengikuti jawaban yang diterima dan menghindari pengujian paralel hanya akan menyembunyikan kesalahan yang sebenarnya diungkapkan oleh tes tersebut. Solusi saya, tentu saja, adalah memperbaiki desain sehingga saya tidak memiliki perilaku buruk ini dalam kode saya.
sumber
[Saya tidak yakin ini adalah jawaban untuk pertanyaan asli, karena stacktrace di sini terlihat sedikit berbeda, tetapi mungkin berguna bagi orang lain.]
Anda bisa mendapatkan tes yang gagal di Surefire saat Anda juga menjalankan Cobertura (untuk mendapatkan laporan cakupan kode). Ini karena Cobertura membutuhkan proxy (untuk mengukur penggunaan kode) dan ada semacam konflik antara keduanya dan proxy Spring. Ini hanya terjadi saat Spring menggunakan cglib2, yang akan terjadi jika, misalnya, Anda punya
proxy-target-class="true"
, atau jika Anda memiliki objek yang sedang di-proxy-kan yang tidak mengimplementasikan antarmuka.Perbaikan normal untuk ini adalah menambahkan antarmuka. Jadi, misalnya, DAO harus berupa antarmuka, yang diimplementasikan oleh kelas DAOImpl. Jika Anda memasang autowire pada antarmuka, semuanya akan berfungsi dengan baik (karena cglib2 tidak lagi diperlukan; proxy JDK yang lebih sederhana ke antarmuka dapat digunakan sebagai gantinya dan Cobertura berfungsi dengan baik dengan ini).
Namun, Anda tidak dapat menggunakan antarmuka dengan pengontrol beranotasi (Anda akan mendapatkan kesalahan runtime saat mencoba menggunakan pengontrol di servlet) - Saya tidak memiliki solusi untuk uji Cobertura + Spring yang pengontrol autowire.
sumber
Saya memiliki masalah serupa: Tes JUnit gagal di Maven Surefire tetapi lolos di Eclipse saat saya menggunakan library JUnit versi 4.11.0 dari SpringSource Bundle Repository. Khusus:
Kemudian saya menggantinya dengan mengikuti JUnit library versi 4.11 dan semuanya berfungsi dengan baik.
sumber
Saya mengalami masalah ini hari ini menguji metode yang mengonversi objek yang berisi
Map
string JSON. Saya berasumsi bahwa Eclipse dan plugin pasti Maven menggunakan JRE berbeda yang memiliki implementasiHashMap
pengurutan yang berbeda atau semacamnya, yang menyebabkan pengujian yang dijalankan melalui Eclipse lulus dan pengujian yang dijalankan pasti gagal (assertEquals
gagal). Solusi termudah adalah dengan menggunakan implementasi Peta yang memiliki pemesanan yang andal.sumber
Anda tidak perlu memasukkan DataSource di JpaTransactionManager karena EntityManagerFactory sudah memiliki sumber data. Coba yang berikut ini:
sumber
Biasanya ketika tes lulus dalam gerhana dan gagal dengan maven, itu adalah masalah jalur kelas karena itu adalah perbedaan utama antara keduanya.
Jadi, Anda dapat memeriksa classpath dengan maven -X test dan memeriksa classpath dari eclipse melalui menu atau di file .classpath di root project Anda.
Apakah Anda yakin misalnya bahwa personervice-test.xml ada di classpath?
sumber
Ini telah membantu saya dalam memecahkan masalah saya. Saya memiliki gejala serupa di mana maven akan gagal namun menjalankan tes junit berjalan dengan baik.
Ternyata pom.xml orang tua saya berisi definisi berikut:
Dan dalam proyek saya, saya menggantinya untuk menghapus argLine:
Semoga ini akan membantu seseorang dalam memecahkan masalah plugin jitu.
sumber
<forkMode>
DITINGGALKAN sejak versi 2.14 Gunakan.forkCount
DanreuseForks
sebaliknya. "Saya memiliki masalah yang sama, dan solusi bagi saya adalah mengizinkan Maven menangani semua dependensi, termasuk toples lokal. Saya menggunakan Maven untuk dependensi online, dan mengonfigurasi jalur build secara manual untuk dependensi lokal. Jadi, Maven tidak mengetahui dependensi yang saya konfigurasikan secara manual.
Saya menggunakan solusi ini untuk menginstal dependensi jar lokal ke Maven:
Bagaimana cara menambahkan file jar lokal di proyek maven?
sumber
Dalam kasus saya, alasannya adalah bug dalam kode. Tes ini mengandalkan urutan elemen tertentu di a
HashSet
, yang ternyata berbeda saat dijalankan di Eclipse atau di Maven Surefire.sumber
Kemungkinan besar file konfigurasi Anda ada di src / main / resources , sementara file tersebut harus di bawah src / test / resources agar berfungsi dengan baik di bawah maven.
https://cwiki.apache.org/UIMA/differences-between-running-unit-tests-in-eclipse-and-in-maven.html
Saya membalas ini setelah dua tahun karena saya tidak dapat menemukan jawaban ini di sini dan saya pikir itu adalah jawaban yang benar.
sumber
src/main/resources
terlihat untuk pengujian, tetapisrc/test/resources
tidak terlihat oleh kode produksi.