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

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

问题描述

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

 布尔testfun(long userId,lond orderId){

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

返回true
}

我试图编写的单元测试如下所示(使用Spock):
$ b $ pre $ @TestFor(OrderService)
@Mock([User,Order])
class OrderServiceSpec extends Specification {
deftest funtest(){

User user = new User(2)
Order order = new Order()
order.metaClass .id = 3 //我要分配域中的订单ID
order.save()
user.addToOrders(订单)
user.save()

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

但是这个测试因为失败而失败订单为空。谁能帮我?
另一个问题是:这个测试是单元测试吗?或者我应该在grails中编写一个集成测试?

解决方案

这取决于您实际尝试测试的内容,但这可以做一个单元测试 - 我只是建议稍微修改一下,以便仅隔离您感兴趣测试的服务方法。你根本不想测试域类,所以最好是模拟/存根你需要的行为来测试服务功能。



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

一些复杂性在于将静态方法(如GORM方法)截掉,但可以使用 GroovySpy 完成工作。



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



以下内容适用于您:

  deftest funtest(){
setup:
// Global,以便它替换所有实例/引用
// mocked类型的持续时间的特征方法。
GroovySpy(User,global:true)

$ b $结果= service.testfun(2,3)

then:
//不需要返回真实对象,所以使用模拟
1 * User.findById(2)>>模拟(用户)
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。


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
    }

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
}
}

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.

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.

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

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
}

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函数对域对象进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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