使用GORM函数测试Grails领域对象的单元测试

5

我在Groovy on Grails的服务类OrderService中有以下代码片段。我想为这个类编写单元测试。用户和订单是领域类。一个用户有多个订单。

boolean testfun(long userId, lond orderId){

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

        return true
    }

我是一个有用的助手,可以将文本翻译为中文。下面是需要翻译的内容(关于IT技术):

我要编写的单元测试如下(使用Spock):

@TestFor(OrderService)
@Mock([User, Order])
class OrderServiceSpec extends Specification{
 def "test funtest"() {

        User user = new User(2)
        Order order = new Order()
        order.metaClass.id = 3// I want to assign the id of the order in domain  
        order.save()        
        user.addToOrders(order)
        user.save()

        expect:
        service.testfun(2,3) == true
}
}

然而,这个测试失败了,因为订单是空的。有人能帮忙吗? 另一个问题是:这个测试是单元测试吗?还是我应该在Grails中编写集成测试?

为什么需要使用 metaClass 来设置 id?在你的 expect 中进行一些简单的断言,以验证 userorder 是否被保存;如果它们没有被保存,你可能需要在保存方法中添加 failOnError: true 来抛出验证异常。 - tylerwal
是的,我尝试检查用户是否已保存。当我执行 User user = new User(2).save() 时,用户被保存了。否则,如果我写 user.save(),用户就不会被保存。 - Ectoras
1个回答

5
这取决于你实际想要测试什么,但这可以是一个单元测试——我建议稍微修改一下,只隔离你感兴趣的服务方法进行测试。你不需要测试领域类,所以最好模拟/存根你需要测试服务功能的行为。
用Spock的支持基于交互的测试通过模拟对象来做这件事是一个好方法。基本上,我们指定当调用服务的testfun()方法时,我们期望调用User.findById()一次,并且还期望调用Order.findByUserAndId()一次。然后,Spock允许我们存根每个方法调用,以便我们指定我们希望该方法返回什么。当我们运行测试时,将使用存根,而不是实际的GORM方法。
一些复杂性存在于存根静态方法(如GORM方法),但您可以使用 GroovySpy来完成工作。
另外,我假设您想使用User.findById()而不是User.findByUserId()
以下是适合您的示例代码:
def "test funtest"() {
    setup:
    // Global so that it replaces all instances/references of the
    // mocked type for the duration of the feature method.
    GroovySpy(User, global: true)
    GroovySpy(Order, global: true)

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

    then:
    // No need to return real objects, so use a mock
    1 * User.findById(2) >> Mock(User)
    1 * Order.findByUserAndId(_ as User, 3) >> Mock(Order)
    result == true

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

    then:
    1 * User.findById(2) >> null
    result == false
}

请注意,我们已经隔离了服务方法。任何协作对象(用户和订单)只通过存根进行交互,我们可以测试服务方法的功能而不必担心GORM。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接