2016-02-12 65 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