用spock测试无效的简单方法

时间:2019-02-13 17:24:59

标签: groovy spock

我有以下方法需要测试:

class Person {

    String getFileName(String number) {
         return "file"+number
    }

    void updateSpec(String number) {
         new File(getFileName(number)).delete()
    }
}

我尝试这样创建测试用例:

def "update spec"() {
        given:
            Person person = new Person()

        when:
            person.updateSpec('1')

        then:
            1 * File.delete()
    }

它说:

Too few invocations for:

1 * File.delete()   (0 invocations)

问题是什么以及如何解决,谢谢!

有没有一种很好的方法来测试此方法?

2 个答案:

答案 0 :(得分:1)

取决于您要测试的内容。首先,您必须使用Mock或Spy才能测试调用计数。

例如,您可以测试是否从getFileName()方法调用了updateSpec()方法,以及是否用'1'这样的参数调用了该方法:

def "update spec"() {
    given:
    Person person = Spy(Person)

    when:
    person.updateSpec('1')

    then:
    1 * person.getFileName('1')
}

如果您确实需要测试是否调用了File.delete(),那么最好稍微更改Person类,因为您需要File模拟,可以检查调用次数:

class Person {
    File getFile(String number) {
        return new File("file" + number)
    }

    void updateSpec(String number) {
        getFile(number).delete()
    }
}

然后可以进行测试:

def "File delete was called"() {
    given:
    File file = Mock(File)
    Person person = Spy(Person)
    person.getFile(_) >> file

    when:
    person.updateSpec('1')

    then:
    1 * file.delete()
}

另一种选择是将一些FileService注入,将File.delete()方法封装到Person类中并测试其发票。

答案 1 :(得分:1)

您只能定义规范下的对象与其模拟的依赖项之间的交互。但是,在您的示例中,您正在“指定”与File类(而不是模拟对象)的交互。参见Spock的Interaction Based Testing。从技术上讲,您可以按照@cgrim答案中的建议实现/更改目标。或者您可以使用PowerMock(不带Spock)之类的工具来模拟除记住之外的几乎所有内容,这种技术仅应作为最后的手段。基本上,如果您遵循最佳设计实践,那么您将永远不需要此类工具。除非您必须处理一些旧代码