使用 GORM 函数对域对象进行单元测试 grails [英] Unit test grails with domain objects using GORM functions

查看:23
本文介绍了使用 GORM 函数对域对象进行单元测试 grails的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Grails 上的 Groovy 中名为 OrderService 的服务类中有以下代码段.我想为这个类做一个单元测试.User 和 Order 是域分类的.一个用户有很多订单.

I have the following piece of code inside a service class named OrderService in Groovy on Grails. I want to make a unit test for this class. User and Order are domain classed. A user has many orders.

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
    }

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

The unit test that I am trying to write is the following (using 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 编写集成测试?

However this test fails because the order is null. Can anyone help me? Another question is: is this test a unit test? or should I write an integration test in grails?

推荐答案

这取决于你实际尝试测试的内容,但这可以是一个单元测试——我只是建议稍微修改它以仅隔离您有兴趣测试的服务方法.您根本不打算测试域类,因此最好模拟/存根测试服务功能所需的行为.

It depends on what you're actually trying to test, but this can be a unit test—I'd just recommend modifying it a little bit to isolate only the service method that you're interested in testing. You're not looking to test the domain classes at all, so it's best to mock/stub the behavior that you need from them to test the service functionality.

Spock 对 基于交互的测试的支持是一个很好的方法 通过模拟对象.基本上我们指定当服务的 testfun() 方法被调用时,我们期望 User.findById() 被调用一次并且 Order.findByUserAndId()代码> 也被调用一次.Spock 然后允许我们对每个方法调用进行存根,以便我们指定我们希望方法返回的内容.当我们运行测试时,将使用存根,而不是实际的 GORM 方法.

A good way to do this is with Spock's support for interaction based testing via mock objects. Basically we specify that when the service's testfun() method is called, we expect User.findById() to be called once and Order.findByUserAndId() to be called once as well. Spock then allows us to stub out each method call so that we specify what we want the method to return. When we run the test, the stub will be used, not the actual GORM method.

一些复杂性在于剔除静态方法(如 GORM 方法),但您可以使用 GroovySpy 来完成工作.

Some complexity lies with stubbing out static methods (like GORM methods), but you can use a GroovySpy to get the job done.

另外,我假设您打算使用 User.findById() 而不是 User.findByUserId()?

Also, I'm assuming you meant to use User.findById() instead of User.findByUserId()?

这些方法应该对您有用:

Something along these lines should work for you:

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.

Note that we've isolated the service method. Any collaborating objects (User and Order) are only being interacted with via stubs and we can test the functionality of the service method without worrying about GORM at all.

这篇关于使用 GORM 函数对域对象进行单元测试 grails的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆