Grails 如何模拟您所使用的类中的方法';在斯波克重新测试

Grails 如何模拟您所使用的类中的方法';在斯波克重新测试,grails,groovy,spock,Grails,Groovy,Spock,我有一个方法,我想在我的网站上测试 public boolean syncUser(username, password){ if (getUserFromDB(username)){ // do work return true } return false } 如何测试syncUser和stub/mock outgetUserFromDB 我什么都试过了,包括 \u*..getUserFromDB(*\u)>>true

我有一个方法,我想在我的网站上测试

public boolean syncUser(username, password){
    if (getUserFromDB(username)){
            // do work
            return true
    }
    return false
}
如何测试
syncUser
和stub/mock out
getUserFromDB

我什么都试过了,包括

\u*..getUserFromDB(*\u)>>true

但它一直试图命中该方法,而不是使用返回值。测试用例如下所示:

void "successfulSyncUser"(){
    given:
    _ * _.getUserFromDB(*_) >> true

    when:
    def syncUserResult = userManagement.syncUser(username, password)

    then:
    syncGuidResult == true
}

您只能在模拟上使用此语句

 _ * _.getUserFromDB(*_) >> true
这意味着你必须首先使用

def mock = Mock(YourClass)
在您的情况下,
getUserFromDB
syncUser
属于同一类。在这种情况下,您不能使用模拟

这是你能做的。您可以使用Groovys元类覆盖当前
UserManagement
实例的实现

void "successfulSyncUser"(){
    given:
    userManagement.metaClass.getUserFromDB = { param1 -> return true }

    when:
    def syncUserResult = userManagement.syncUser(username, password)

    then:
    syncGuidResult == true
}
请找到一个如何使用Groovy Magic覆盖现有方法的简单示例:)

这将产生以下输出:

Foo
Foo
Bar
Foo

我还要补充一点,将
getUserFromDB()
方法移动到一个单独的类是个好主意,这似乎违反了SRP。这样,模拟单个字段就不会有任何问题了。@Opal我有多种情况使用getUserFromDB,因此我在它自己的方法中没有复制代码。但是你需要将该方法移动到另一个类,以便用Spock模拟它。我在这里看不到/获取SRP冲突。这个类被称为“userManagement”,它就是这么做的。创建另一个类(以及查看代码时的另一个精神跳跃)来做一件小事来解决单元测试框架的限制似乎有些古怪。最干净的解决方案是将
getUserFromDB
移动到一个单独的类。如果您真的想要半模拟,可以使用
间谍
实现。有关详细信息,请参阅。
Foo
Foo
Bar
Foo