使用mockFor在groovy单元测试中模拟Sql.call()

时间:2016-09-28 21:25:42

标签: unit-testing groovy mocking

我试图在groovy.sql.Sql中模拟newInstance()call()

package com.sample

import grails.test.GrailsUnitTestCase
import groovy.mock.interceptor.MockFor
import groovy.sql.Sql

class MySampleTests extends GrailsUnitTestCase {

    void testThat_SqlCall_IsInvokedWithexpectedQuery() {
        def mockSql = new MockFor(Sql.class)

        mockSql.demand.newInstance { def datasource->
            return mockSql
        }

        mockSql.demand.call { def sql ->
            return 0
        }

        mockSql.use {
            MySample targetObject = new MySample()
            targetObject.myMethod()
        }
    }
}

这是目标代码:

package com.sample

import groovy.sql.Sql

class MySample {
  def dataSource

  def myMethod() {
    def conn = Sql.newInstance(dataSource)
    conn.call("test")
  }
}

错误地说:

groovy.lang.MissingMethodException: No signature of method: groovy.mock.interceptor.MockFor.call() is applicable for argument types: (java.lang.String) values: [test]

该错误使得看起来call()方法没有被模拟。是这样的吗?什么是修复它?

1 个答案:

答案 0 :(得分:0)

mockSql.demand.call替换mockSql.metaClass.call提供了一种模拟方法,但需要手动验证调用该方法以及参数值:

package com.sample

import grails.test.GrailsUnitTestCase
import groovy.mock.interceptor.MockFor
import groovy.sql.Sql

class MySampleTests extends GrailsUnitTestCase {

    void testThat_SqlCall_IsInvokedWithexpectedQuery() {
        def mockSql = new MockFor(Sql.class)
        def callInvoked = 0

        mockSql.demand.newInstance { def datasource->
            return mockSql
        }

        mockSql.metaClass.call { def sql ->
            assert sql == "test"
            ++callInvoked
            return 0
        }

        mockSql.use {
            MySample targetObject = new MySample()
            targetObject.myMethod()
        }

        assert callInvoked == 1
    }
}

我不知道足够的常规但还不明白为什么会这样,但它解决了我的问题。

其他外观更改以及从mySql.use {}移出targetObject实例化导致:

package com.sample

import grails.test.GrailsUnitTestCase
import groovy.mock.interceptor.MockFor
import groovy.sql.Sql

class MySampleTests extends GrailsUnitTestCase {

    MySample targetObject = new MySample()

    void testThat_SqlCall_IsInvokedWithexpectedQuery() {
        def mockSql = new MockFor(Sql)
        def callInvoked = 0

        mockSql.demand.newInstance { datasource->
            mockSql
        }

        mockSql.metaClass.call { sql ->
            assert sql == "test"
            ++callInvoked
            0
        }

        mockSql.use {
            targetObject.myMethod()
        }

        assert callInvoked == 1
    }
}