2016-02-12 67 views
0

我是使用Spock在Grails應用程序中進行單元測試的新手。不過,我想問一下以下問題。假設我想爲以下函數testfun運行測試。Grails Spock嘲笑一個對象

class TestFun{ 

boolean testfun(long userId, long orderId){ 

    User user = User.findByUserId(userId) 
    if(user == null)return false 
    Order order = Order.findByUserAndId(user, orderId) 

    HashMap<String, Object> = orderContent 
    orderContent= order.orderContent // the order has an element orderContent for storing the elements that one user orders 

    if(orderContent!=null){ 
     orderContent.put("meal",1) 
     order.orderContent = orderContent 
     return true 
    } 

    return false 
} 
} 

在這種情況下,相應的單元測試是:

class TestFun extends Specification { 

    def setup() { 

     GroovySpy(User, global: true) 
     GroovySpy(Order, global: true) 
    } 
def "test funtest"() { 

     User user = new User(2).save() 
     Order order = new Order(3).save() 

     when: 
     service.testfun(2,3) == result 

     then: 
     2*User.findByUserId(2) >> Mock(User) 
     1*Order.findByUserAndId(_ as User, 1)>> Mock(Order) 
     result == true 
} 
} 

不過,我覺得我有嘲笑order.orderContent,我不知道如何嘲笑它。現在測試失敗,因爲orderContent爲null,所以testfun返回false。

任何人都可以幫助我嗎?

回答

1

在這裏有幾件事情,希望修復它們會幫助您測試運行和傳遞。

我記不得某些,但我相信GroovySpy是一箇舊功能,它不用於Spock測試。您應該在類定義之前使用@Mock批註來指定您想要模擬的域類,而不是使用它來模擬域類。

儘管您可以模擬域類,但如果需要進行多個測試,您還需要使用這些對象(setup:塊或setup()方法)實際填充內存數據庫。

您提到創建模擬,並使用Spock Mock()方法將創建該對象的模擬,但您不希望將其用於域對象。它通常用於將被手動注入到測試類中的服務類。

當保存一個模擬域類時,我建議包括參數flush: true, failOnError: true,這樣任何失敗的驗證都會立即顯示在適當的行上。沒有這個,你可以在測試中稍後發生一些奇怪的錯誤。

我不知道你在做什麼when:區塊,但是你不應該在==這個位置做斷言,做所有then:區塊。

鑑於這一切,我覺得你的測試類應該看起來更像是這樣的:

@Mock([User, Order]) 
class TestFun extends Specification { 

    def setup() { 
     // This object will have an id of 1, if you want a different id, you can either specify it, or create more objects 
     User user = new User(first: "john", last: "doe").save(flush: true, failOnError: true) 
     new Order(user: user).save(flush: true, failOnError: true) 
    } 

    def "test funtest"() { 

     User user = new User(2).save() 
     Order order = new Order(3).save() 

     when: 
     boolean result = service.testfun(1, 1) 

     then: 
     // Optionally you can just use "result" on the next line, as true will be assumed 
     result == true 
    } 
} 
+0

非常感謝您MND您的時間來寫這個答案。不幸的是,當我嘗試做類似的事情時,測試失敗了,因爲它不會返回true,而是錯誤的。 – Ectoras

+0

@Ectoras,我只是再次查看代碼,它返回null,因爲'orderContent'是空的 - 我沒有提供,當保存Order對象時。我會建議添加一個元素來查看它是否有效。如果這不起作用,請包括「Order」和「Users」類的完整代碼,然後我可以幫你解決。 – mnd