首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Grails 2.4.4 :如何模拟域内的临时服务?

Grails 2.4.4 :如何模拟域内的临时服务?
EN

Stack Overflow用户
提问于 2015-03-03 01:53:33
回答 1查看 757关注 0票数 1

我已经试着解决这个问题两天了,我真的被卡住了,我很沮丧。我有一个域对象,其中包含一个用于自定义验证的服务。域如下所示:

代码语言:javascript
复制
class Llama { 
String name
transient myFetcherService

static transients = [
            'myFetcherService'
    ]

static constraints = {
        name validator: { val, obj ->
            if (obj.nameExists(val) == true) {
                //return some error here.
            }
        }
    }

protected boolean nameExists(String name) {
        List<Llama> llamasList = myFetcherService.fetchExistingLlamasByName(name)

        if (llamasList.isEmpty()) {
            return false
        }

        return true
    }
}

现在,我有了另一个服务,它只保存一个Llama对象列表。它看起来是这样的:

代码语言:javascript
复制
class LlamaFactoryService {

   public void createLlamas(List<String> llamaNames) {
     llamaNames.each { name ->
         new Llama(name: name).save()
     }
   }

}

在我的测试中。我一直收到这个错误:

代码语言:javascript
复制
Failure:  createLlamas should create Llammas (com.myLlamaProject.LlamaFactoryServiceSpec)
|  java.lang.NullPointerException: Cannot invoke method myFetcherService on null object

我不明白。在我的测试中,在“给定”部分添加了服务的metaClass。当它尝试保存时,它会告诉您该服务为空。我的测试是这样的:

代码语言:javascript
复制
given:
def myFetcherService = mockFor(MyFetcherService)   
myFetcherService.demand.fetchExistingLlamasByName {def name -> return []}
Llama.metaClass.myFetcherService = myFetcherService.createMock()

when:
service.createLlamas(['Pablo','Juan','Carlos'])

then:
//some validations here....

我还尝试在nameExists()方法上使用metaClass,如下所示:

代码语言:javascript
复制
Llama.metaClass.myFetcherService = { def name -> false }

,但它给了我与上面的相同的nullPointerException。谁能给我指个方向?我有点卡住了。:(

提前感谢您的阅读和帮助。

EN

回答 1

Stack Overflow用户

发布于 2015-03-03 07:55:41

您正在使用单元测试,而单元测试的一般规则是,bean通常不是为您创建的,因此您需要自己注入它们。

(代码编辑以反映我对问题的误解)我认为您需要一个类似以下内容的测试模式:

代码语言:javascript
复制
given:
def mockMyFetcherService = Mock(MyFetcherService) // create the mock
Llama.metaClass.getMyFetcherService = { mockMyFetcherService } // inject the dependency
def returnList = []  // let's just define this here and you can re-use this pattern in other tests more easily

when:
service.createLlamas(['Pablo','Juan','Carlos'])

then:
// tell Spock what you expect to have happen with your Mock - return the List you defined above
3 * mockFetcherService.fetchExistingLlamasByName(_) >> returnList

如果将服务注入metaClass不起作用(suggested here),您可以始终尝试在单元测试本身中使用defineBeans{}闭包(http://www.block-consult.com/blog/2011/08/17/inject-spring-security-service-into-domain-class-for-controller-unit-testing/)。

因此,您可以尝试:

代码语言:javascript
复制
defineBeans {
  myFetcherService(MockMyFetcherService)
}

其中MockMyFetcherService是在定义测试的同一文件中定义的。这就是followed here的方法

有关更多Spock交互的示例,请参阅here

如果您使用的是Grails 2.4.3或更低版本,则需要将CGLIB放在BuildConfig.groovy中,但我看到here在2.4.4中已经为您完成了这一点,所以您应该可以使用Mock(classname)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28816354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档