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

添加其他存根时调用第一个存根

酆恩
2023-03-14

我有以下要测试的对象:

   public class MyObject {

    @Inject
    Downloader downloader;

    public List<String> readFiles(String[] fileNames) {
        List<String> files = new LinkedList<>();
        for (String fileName : fileNames) {
            try {
                files.add(downloader.download(fileName));
            } catch (IOException e) {
                files.add("NA");
            }
        }
        return files;
    }
}

这是我的测试:

@UseModules(mockTest.MyTestModule.class)
@RunWith(JukitoRunner.class)
public class mockTest {

    @Inject Downloader downloader;
    @Inject MyObject myObject;

    private final String[] FILE_NAMES = new String[] {"fail", "fail", "testFile"};
    private final List<String> EXPECTED_FILES = Arrays.asList("NA", "NA", "mockContent");

    @Test
    public void testException() throws IOException {
        when(downloader.download(anyString()))
                .thenThrow(new IOException());

        when(downloader.download("testFile"))
                .thenReturn("mockContent");

        assertThat(myObject.readFiles(FILE_NAMES))
                .isEqualTo(EXPECTED_FILES);
    }

    public static final class MyTestModule extends TestModule {
        @Override
        protected void configureTest() {
            bindMock(Downloader.class).in(TestSingleton.class);
        }
    }
}

我正在覆盖特定参数的匹配器。我正在存根download()方法,以便它为特定参数返回一个值,否则抛出一个IOException,该IOException由MyObject处理。读取文件。

奇怪的是,第二个存根(downloader.download(“testFile”))在第一个存根(downloader.download(anyString()))中抛出IOException集。我通过在第一个存根中抛出不同的异常来验证这一点。

有人能解释一下为什么在添加其他存根时会引发异常吗?我认为创建存根不会调用方法/其他存根。

共有3个答案

闾丘成双
2023-03-14

您的第二条mock语句将被第一条mock语句覆盖(因为两条mock语句都在传递字符串参数)。如果您想通过模拟测试进行覆盖和回溯,请编写两个不同的测试用例。

习斌
2023-03-14

我认为创建存根不会调用方法/其他存根。

这种假设是错误的,因为stubing正在调用mocks方法。您的测试方法仍然是纯java!

由于任何字符串的存根都将覆盖任何特定字符串的存根,因此您必须为两个特定参数编写两个测试或存根:

when(downloader.download("fail")).thenThrow(new IOException());

when(downloader.download("testFile")).thenReturn("mockContent");

Mockito是一段非常复杂的代码,它会尽最大努力让您可以编写

when(downloader.download(anyString())).thenThrow(new IOException());

这意味着“downloaders mockdownload方法使用anyString参数然后抛出IOException”(即,可以从左到右读取)。

然而,由于代码仍然是纯java,因此调用序列实际上是:

String s1 = anyString(); // 1
String s2 = downloader.download(s1); // 2
when(s2).thenThrow(new IOException()); // 3

在幕后,莫奇托需要这样做:

  1. 为任何字符串参数
  2. 注册一个ArgumentMatcher
  3. 下载器mock上注册方法调用下载,其中参数由之前注册的ArgumentMatcher
  4. 定义
  5. 在mock上为先前注册的方法调用注册一个操作

如果你现在打电话

 ... downloader.download("testFile") ...

下载程序模拟检查是否有“testFile”的操作寄存器(有,因为任何字符串都已经有操作),并相应地抛出IOException。

唐彬炳
2023-03-14

问题是当你写

when(downloader.download("testFile")).thenReturn("mockContent");

首先要调用的是downloader。下载,您已经将其存根以引发异常。

解决方案是使用Mockito提供的稍微更通用的存根语法。这种语法的优点是它在存根时不会调用实际方法。

doThrow(IOException.class).when(downloader).download(anyString());
doReturn("mock content").when(downloader).download("test file");

我在这里的回答中列出了第二种语法的其他优点

 类似资料:
  • 如果我有一个接受两个回调的函数的存根,当存根函数被调用时,我如何连接sinon.js来调用两个回调? 例如,这里有一个我想存根的函数,它接受两个函数作为参数: 我可以用sinon来称呼其中一个论点: 或者 但我似乎不能让两者都被召唤。如果我尝试: 或者 那么sinon只会调用第二个参数。如果我以另一个顺序连接它,那么sinon将调用第一个参数。然而,我希望两者都被一个接一个地称呼。

  • 问题内容: 加载页面后,我将对php脚本执行Ajax调用,这将更新服务器。但是,此脚本有时可能需要一分钟才能完成,并且在脚本运行时,我无法执行我需要处理的其他Ajax调用- 即第一个Ajax调用不应中断其他Ajax调用。任何想法如何做到这一点? 首次Ajax通话: 第二个Ajax调用(用户触发的调用): 问题答案: 腺苷的上述评论是正确的。 “在PHP中,一次只能在一个会话上运行一个脚本,以免覆盖

  • 问题内容: 我想不出一种方法来对从定义此函数的同一模块中调用的函数进行存根(存根似乎不起作用)。这是一个例子: myModule.js: myModule.test.js: 这让我想起了(几乎)不可插拔的Java静态函数。 知道如何实现我要做什么吗?我知道在另一个模块中进行提取将起作用,但这不是我在这里尝试做的。我也知道,调用的方法与关键字也将工作中,我逐步使用困惑 在这方面(因为我没有使用OOP

  • 问题内容: 是否有一种方法可以使每次调用方法时都会被调用的“超级方法”,即使对于未定义的方法也是如此?有点像这样: 编辑- 细节:我有一个库,该库进行了很多更新,并且每次更新都变得晦涩难懂。为了简化我的工作流程,我正在使程序自动更新库(需要执行我想做的事情,我不会具体说明原因,但是我的程序可以与将来的更新一起使用)并且我有混淆映射与库一起下载时,我想制作一种例如称为的代理,然后在我调用它时,将获得

  • 问题内容: 我正在使用Mockito。我想在调用未存根方法时抛出一个。 有什么办法吗? 问题答案: 您可以为模拟设置默认答案。所有未存根的方法都将使用此默认答案。 请注意,您 不能 使用此功能,因为该方法是在方法调用之前(嘲笑when()调用如何工作的?),并且它将在模拟进入存根模式之前抛出a 。 因此,您必须使用它来工作。

  • 我想验证各种日期字段是否被正确更新,但我不想在预测< code>new Date()何时被调用上浪费时间。我如何剔除日期构造函数? 如果相关,这些测试在节点应用程序中运行,我们使用TypeScript。