2015-07-04 39 views
3

想象一下,您有一些簡單的代碼,您可以在一個事務中將兩行插入到數據庫中。如何測試交易數據庫代碼?

如何讓第二個測試失敗以檢查第一個是否回滾?

它會是一個web服務,我會通過元編程嘲笑它,以便讓第二次調用失敗。

但是對於數據庫代碼,我不確定。是否可能有某種類型的jdbc驅動程序會在第7次操作中引發異常(比方說)?

好吧,讓我們更具體:

想象一下,你有一些遺留代碼。它的結構不夠好,但你也不想重構它(我們先寫一些測試!)。交易行爲似乎存在問題,您希望測試您的代碼。

由於代碼的基本工作原理,很難通過違反約束使其部分失敗。

所以我想在我的測試中做什麼是模擬數據庫發生故障(可能是因爲存在死鎖,不可用,磁盤已滿或類似情況)或您「拔出插頭」時發生的情況。

+0

我很確定你可以用[spock]來執行此操作(https://code.google.com/p/spock/wiki/Interactions) – rcgeorge23

+0

是的,但如何...找不到示例... – rdmueller

+2

違反一些缺點第二行添加traint。任何會導致第二次插入失敗的應該是足夠的,不是嗎? – railsdog

回答

1

集成測試將是測試事務和回滾的合適位置。像這樣的樣本的東西應該足夠了:

package com.example 

import grails.test.mixin.integration.Integration 
import grails.transaction.* 
import spock.lang.* 
import org.springframework.beans.factory.annotation.Autowired 

@Integration 
@Rollback 
class TransactionIntSpec extends Specification { 

    @Autowired 
    FooService service 

    void "test transaction rollback"() { 
     given: 'bar service throws exception' 
     service = Mock(FooService) { 
      serviceBar() >> { throw new Exception() } 
     } 

     when: 
     service.serviceMethod() 

     then: 
     !Foo.count() && !Bar.count() 
    } 

    void "test transaction successfull"() { 
     when: 
     service.serviceMethod() 

     then: 
     Foo.count() && Bar.count() 
    } 
} 

其中FooBar只是簡單的域類和服務類會是什麼樣子:

package com.example 

import grails.transaction.Transactional 

@Transactional 
class FooService { 

    def serviceMethod() { 
     serviceFoo() 
     serviceBar() 
    } 

    def serviceFoo() { 
     new Foo().save(flush: true, failOnError: true) 
    } 

    def serviceBar() { 
     new Bar().save(flush: true, failOnError: true) 
    } 
} 

Grails的測試3.0.2

+0

好的,這裏使用的技巧是將方法/事務分解成可以模擬的子方法。所以如果'serviceFoo'和'serviceBar'是內聯的,這是行不通的,對嗎? – rdmueller

+0

你可以按照@railsgod在評論中提出的建議。 – dmahapatro