当前位置: 首页 > 知识库问答 >
问题:

Spock模拟在collabolator内部返回null,但在feature方法中不返回null

阚亮
2023-03-14

我对Spock Mock()对象有一个问题。我有一个java类正在尝试测试。这个类做了一些我想模拟的ftp内容。我的示例代码

class ReceiveDataTest extends Specification{
    String downloadPath = 'downloadPath';
    String downloadRegex = 'downloadRegex';
    SftpUtils sftpUtils = Mock();
    ReceiveData receiveData;

    def setup(){
        sftpUtils.getFileNames(downloadPath,downloadRegex) >> ['file1', 'file2']
        receiveData= new ReceiveData()
        receiveData.setDownloadPath(downloadPath)
        receiveData.setDownloadRegex(downloadRegex)
        receiveData.setSftpUtils(sftpUtils);

    }

    def "test execute"() {
        given:
        def files = sftpUtils.getFileNames(downloadPath,downloadRegex)
        files.each{println it}
        when:
        receiveData.execute();
        then:
        1*sftpUtils.getFileNames(downloadPath,downloadRegex)
    }

}

public class ReceiveData(){

  //fields, setters etc

    public void execute() {
        List<String> fileNames = sftpUtils.getFileNames(downloadPath, downloadRegex);

        for (String name : fileNames) {
            //dowload and process logic
        }

    }
}

现在,在“test execute”中的文件。each{}打印预期的内容。但当调用receivedata.execute()时,我的sftpUtils返回null。知道为什么吗?

Mockito.when(sftpUtils.getFilenames(downloadPath, downloadRegex)).thenReturn(filenamesList);
receiveData.execute();

Mockito.verify(sftpUtils).getFilenames(downloadPath, downloadRegex);
//this is what I want to test and resides inside for loop
Mockito.verify(sftpUtils).download(downloadPath, filenamesList.get(0));
Mockito.verify(sftpUtils).delete(downloadPath, filenamesList.get(0));

共有1个答案

司寇瑾瑜
2023-03-14

主要的问题是您没有将响应生成器(>>部分)包含在期望中(即then:块中的“1*...”部分)。

这在spock文档中有很好的解释。

>

  • http://spockframework.org/spock/docs/1.0/interaction_based_testing.html#_combining_mocking_and_stubing

    您不必在setup:块中声明存根。您只需要在then:块中指定它一次--即使这是在调用receivedata.execute()之后。由于Groovy AST转换,这就是spock的部分魔力。而且由于(非共享的)字段在每次测试之前都被重新初始化(更多的是基于AST的魔术),在这种情况下甚至不需要setup()。

    另一件奇怪的事情是,您既删除了sftputils.getFileNames(),又从测试代码中调用了它。模拟和存根用于替换从测试中的系统调用的协作器。没有理由调用测试驱动程序的存根。因此,从给定块中删除对getFilenames()的调用,并让测试中的代码调用它(正如它所做的那样)。

    Groovy允许您简化对Java set和get方法的调用。看看下面receiveData的初始化。在Groovy中使用def是可以的。让编译器为您计算出数据类型。

    导致类似于:

    class ReceiveDataTest extends Specification {
    
        // only use static for constants with spock
        static String PATH = 'downloadPath'
        static String REGEX = 'downloadRegex'
    
        def mockSftpUtils = Mock(SftpUtils)
    
        def receiveData = new ReceiveData(downloadPath : PATH,
                                          downloadRegex : REGEX,
                                          sftpUtils : mockSftpUtils)
    
        def "execute() calls getFileNames() exactly once"() {
           when:
               receiveData.execute()
           then:
                1 * mockSftpUtils.getFileNames(PATH, REGEX) >> ['file1', 'file2']
                0 * mockSftpUtils.getFileNames(_,_) 
    
               // The second line asserts that getFileNames() is never called
               // with any arguments other than PATH and REGEX, aka strict mocking
               // Order matters! If you swap the lines, the more specific rule would never match
        }
    }
    

  •  类似资料:
    • 当我测试模拟外部调用时,我没有看到报告的模拟值,而是,并且我的测试失败。我可以在测试类中看到模拟值(报告),但在类中看不到,并且应用程序(方法返回)没有像我预期的那样被修改。 我的期望是:当我在Impl类中模拟外部调用时,模拟值应该在那里可用,其余的一切都会发生,就好像调用了真正的方法来完成单元测试一样。 实现代码: 测试代码:

    • 我试图测试一个简单POST Rest调用,但存在NullPointerException。 我的RestController: 我的单元测试: 由于以下错误,此测试失败:NullPointerException,确切地说,response ResponseEntity对象为Null。 verify输出将执行以下操作: 知道为什么响应是空的吗?我为测试使用了正确的注释,因此应该注入模拟。也许我在这里

    • 我创建了一个接口,以便可以在对话和片段之间进行通信。 目标:当用户从对话框中选择任何内容时,应将其显示在文本视图中。 在这个界面中,我创建了一个界面方法,在主活动中调用,并传递用户在对话框中选择的值。与用户选择的值一起,在我的片段中,我创建了一个方法,将文本视图设置为该值。然而,每当我调用该方法时,它总是返回null。 我对日志进行了大量测试,发现通过我的方法传递的值不是空的,一切似乎都按照我想要

    • 我在这件事上纠结了一段时间。是否可以模拟新URL(URL)。openStream()返回一个文件。广州?我正在使用斯波克来尝试这样做。 测试类 或者我最好编写一个私有方法来返回流?

    • 给定一个类Foo 为什么我用Spock来嘲笑Foo 调用总是返回false? 不确定这是否有区别,但测试是在Groovy/Spock中进行的,而Foo是在Java8中进行的。

    • 我试图模拟一些方法调用,但不幸的是我一直返回null。你能帮我指出我可能出错的地方吗?我正在使用time(). thenBack(),我觉得我正确地模拟了返回变量。事先非常感谢。我是JUnit和Mockito的新手,所以如果我错过了任何明显的东西,我很抱歉。 ServiceTest.java Service.java