【问题标题】:how do you mock out methods from the class you're testing in spock你如何从你在 spock 中测试的类中模拟出方法
【发布时间】:2014-09-09 22:57:23
【问题描述】:

我有一个方法想在我的站点中测试

public boolean syncUser(username, password){
    if (getUserFromDB(username)){
            // do work
            return true
    }
    return false
}

如何测试syncUser 和存根/模拟getUserFromDB

我什么都试过了,包括

_ * _.getUserFromDB(*_) >> true

但它一直试图点击方法而不是使用返回值。测试用例如下:

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

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

    then:
    syncGuidResult == true
}

【问题讨论】:

  • 最干净的解决方案是将getUserFromDB 移动到一个单独的类。如果你真的想要一个半模拟,你可以使用Spy 来实现它。详情请见docs.spockframework.org

标签: grails groovy spock


【解决方案1】:

您只能在模拟中使用此语句。

 _ * _.getUserFromDB(*_) >> true

这意味着你必须首先使用

def mock = Mock(YourClass)

在您的情况下,getUserFromDBsyncUser 属于同一类。在这种情况下,您不能使用模拟。

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

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

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

    then:
    syncGuidResult == true
}

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

class Person {    
    String sayHello() { 'Foo' }
}

def a = new Person()
def b = new Person()

println a.sayHello()
println b.sayHello()

a.metaClass.sayHello = { 'Bar' }

println a.sayHello()
println b.sayHello()

这将导致以下输出:

Foo
Foo
Bar
Foo

【讨论】:

  • 我还要补充一点,将getUserFromDB() 方法移动到一个单独的类是个好主意——这似乎违反了 SRP。那么,模拟单个字段就不会有任何问题了。
  • 但是您需要将该方法移动到不同的类中才能使用 Spock 模拟它
  • 我在这里没有看到/得到 SRP 违规。该类称为“userManagement”,这就是它正在做的事情。创建另一个类(以及查看代码时的另一个心理跳跃)来做一件小事来解决单元测试框架的限制似乎很麻烦。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2023-01-15
  • 1970-01-01
  • 2010-11-17
  • 2016-06-01
  • 1970-01-01
  • 2012-08-26
相关资源
最近更新 更多