@Test'ten sonra geri alma işlemi


86

Her şeyden önce, StackOverflow'da bu konuda çok sayıda konu buldum, ancak hiçbiri bana gerçekten yardımcı olmadı, bu yüzden muhtemelen yinelenen bir soru sorduğum için üzgünüm.

Bahar testini kullanarak JUnit testleri çalıştırıyorum, kodum şöyle görünüyor

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {})
public class StudentSystemTest {

    @Autowired
    private StudentSystem studentSystem;

    @Before
    public void initTest() {
    // set up the database, create basic structure for testing
    }

    @Test
    public void test1() {
    }    
    ...  
}

Benim sorunum, testlerimin diğer testleri etkilememesini istemem. Bu nedenle, her test için geri alma gibi bir şey oluşturmak istiyorum. Bunun için çok aradım ama şimdiye kadar hiçbir şey bulamadım. Bunun için Hibernate ve MySql kullanıyorum


Geri alma ile ne demek istiyorsun? Veritabanını mı temizliyorsunuz?
Gaurav

5
onu çalıştırdıktan sonra olduğu duruma tam olarak ayarlamakinitTest
Jan Vorcak

Yanıtlar:


129

@TransactionalTestinizin üzerine ek açıklama eklemeniz yeterlidir:

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"testContext.xml"})
@Transactional
public class StudentSystemTest {

Varsayılan olarak Spring, test yönteminizi ve @Before/ @Aftergeri aramalarınızı çevreleyen yeni bir işlem başlatacak ve sonunda geri dönecektir. Varsayılan olarak çalışır, bağlamda bir işlem yöneticisine sahip olmak yeterlidir.

Kimden: 10.3.5.4 İşlem yönetimi (kalın maden):

TestContext çerçevesinde işlemler TransactionalTestExecutionListener tarafından yönetilir. Test sınıfınızda açıkça beyan etmeseniz bile bunun varsayılanTransactionalTestExecutionListener olarak yapılandırıldığını unutmayın @TestExecutionListeners. Bununla birlikte, işlemler için desteği etkinleştirmek için, anlambilim PlatformTransactionManagertarafından yüklenen uygulama bağlamında bir çekirdek sağlamanız gerekir @ContextConfiguration. Ek olarak, testleriniz için sınıf veya yöntem düzeyinde beyan etmeniz gerekir@Transactional .


2
Peki, bunu daha önce denedim ve hala çalışmıyor, belki ... sorun PlatformTransactionManager'ı tanımlamamış olabilir miyim, bunu nasıl yapabilirim?
Jan Vorcak

@javo: Veritabanını nasıl değiştiriyorsunuz? Jpa / Hibernate / JdbcTemplate / ... kullanıyorsanız, bazılarının olması gerekir PlatformTransactionManager. Aksi takdirde Spring işlemlerinizi ve veri tabanınızı nasıl bilecek?
Tomasz Nurkiewicz

1
Bu yanıttaki bağlantı artık doğru değil; bkz aşağıda user2418306 yanıtını Bahar belgelerine doğru bağlantı ve daha bağlam için.
DaveyDaveDave


Tabloda bir eki test ediyorum. @Transactional ile, veri tabanına karşı insert komutu bile verilmez (konsolun hibernate show-sql true olduğunu görebiliyorum). Çoğu durumda iyi çalışır. Ancak testlerimden biri, veritabanının bir veritabanı kısıtlaması nedeniyle bir DataAccessException oluşturduğunu kontrol ediyor. Bu durumda, geri alma "bellekte" olduğundan ve veritabanı hiçbir zaman çağrılmadığından test başarısız olur. Çözüm: Sınıf düzeyinde değil @Transactional, @Testyöntem düzeyinde kullanın .
Paulo Merson

17

Bir kenara: Tomasz Nurkiewicz'in cevabını değiştirme girişimi reddedildi:

Bu düzenleme, gönderiyi okumayı biraz daha kolay, bulmayı daha kolay, daha doğru veya daha erişilebilir hale getirmez. Değişiklikler ya tamamen gereksizdir ya da okunabilirliğe aktif olarak zarar verir.


Entegrasyon testi ile ilgili dokümantasyonun ilgili bölümüne doğru ve kalıcı bağlantı .

İşlemler için desteği etkinleştirmek için, semantik yoluyla yüklenen bir PlatformTransactionManagerçekirdeği yapılandırmanız gerekir .ApplicationContext@ContextConfiguration

@Yapılandırma
@PropertySource ("application.properties")
public class Persistence {
    @Autowired
    Çevre env;

    @Fasulye
    DataSource dataSource () {
        yeni DriverManagerDataSource (
                env.getProperty ("datasource.url"),
                env.getProperty ("datasource.user"),
                env.getProperty ("datasource.password")
        );
    }

    @Fasulye
    PlatformTransactionManager transactionManager () {
        yeni DataSourceTransactionManager (dataSource ()) döndür;
    }
}

Ek olarak, @Transactionaltestleriniz için sınıf veya yöntem düzeyinde Spring'in açıklamasını beyan etmeniz gerekir .

@RunWith (SpringJUnit4ClassRunner.class)
@ContextConfiguration (sınıflar = {Persistence.class, SomeRepository.class})
@Transactional
genel sınıf SomeRepositoryTest {...}

Bir test yöntemine ek açıklama @Transactionaleklemek, testin varsayılan olarak test tamamlandıktan sonra otomatik olarak geri alınacak bir işlem içinde çalıştırılmasına neden olur. Bir test sınıfına not eklenmişse @Transactional, o sınıf hiyerarşisindeki her test yöntemi bir işlem içinde çalıştırılır.


12

Eklemeden bahseden cevaplar @Transactionaldoğrudur, ancak basit olması için sadece test sınıfınıza sahip olabilirsiniz extends AbstractTransactionalJUnit4SpringContextTests.


1
Sınıf düzeyinde '@Transactional' notu eklemek işe yaramıyor, her fonksiyon için ayrı ayrı '@Transactional' notu eklemek işe yarıyor ve AbstractTransactionalJUnit4SpringContextTests de çalışıyor
Kamil Nekanowicz

5

Biliyorum, cevap göndermek için çok geç kaldım, ama birisine yardımcı olabileceğini umuyorum. Artı, yaşadığım bu sorunu testlerimle çözdüm. Testimde sahip olduğum şey bu:

Test sınıfım

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "path-to-context" })
@Transactional
public class MyIntegrationTest 

Bağlam xml

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="${jdbc.driverClassName}" />
   <property name="url" value="${jdbc.url}" />
   <property name="username" value="${jdbc.username}" />
   <property name="password" value="${jdbc.password}" />
</bean>

Hala problemim vardı, veritabanı otomatik olarak temizlenmiyordu.

BasicDataSource'a aşağıdaki özelliği eklediğimde sorun çözüldü

<property name="defaultAutoCommit" value="false" />

Umarım yardımcı olur.


Öyleyse, ifadelerinizi elle mi yazıyorsunuz? Verilerinizin veritabanınıza yazıldığından emin misiniz?
franta kocourek

Bahar İşlemlerini anlamakta güçlük çeken herkes için, veri kaynağınızın otomatik işleme ayarlı OLMADIĞINDAN emin olun, aksi takdirde @Transactional'ın neden hiçbir şey yapmadığını anlamaya çalışırken çıldıracaksınız.
Joe Ernst

2

Testinizi bir Spring bağlamı ve bir işlem yöneticisi ile çalıştırmanız gerekir, örneğin,

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"/your-applicationContext.xml"})
@TransactionConfiguration(transactionManager="txMgr")
public class StudentSystemTest {

     @Test
     public void testTransactionalService() {
         // test transactional service
     }

     @Test
     @Transactional
     public void testNonTransactionalService() {
         // test non-transactional service
     }
}

Daha 3.5.8. Transaction Managementfazla ayrıntı için Yay referansı bölümüne bakın .


0

Eklemenin yanı sıra @Transactionalüzerinde @Testyöntemle, ayrıca eklemem gerekiyor@Rollback(false)


-5

Geri Almayı devre dışı bırakabilirsiniz:

@TransactionConfiguration(defaultRollback = false)

Misal:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@Transactional
@TransactionConfiguration(defaultRollback = false)
public class Test {
    @PersistenceContext
    private EntityManager em;

    @org.junit.Test
    public void menge() {
        PersistentObject object = new PersistentObject();
        em.persist(object);
        em.flush();
    }
}

6
Bu, OP'nin istediği şeyin tam tersi
Adam Michalik

Bu, kabul edilen cevaba bir yorum olmalıydı.
DerMike
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.