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

为什么mockito在java 7而不是java 6中的then回报()上报告错误

陆飞鸿
2023-03-14

Mockito在模拟客户端时报告未完成的存根错误。getPrograms()应该返回SortedSet

下面是模拟客户端时触发错误的代码。getPrograms()

private void prepareScheduleChangePreconditions() {
    Client client = mock(Client.class);
    TimeTable tt = BuilderUtil.buildTable(AcceleratedScheduleTimeTable.Schedule.NORMAL, "08:00");
    when(clientRepository.findByCode(anyString())).thenReturn(client);
    //Error is reported for next line of code
    when(client.getPrograms()).thenReturn(new TreeSet<Program>(Collections.singleton(program)));
    when(event.getTimeTable()).thenReturn(tt);      
}

以下是错误输出:

Tests in error:
  testExampleScheduleChangeNotify1(com.example.service.impl.ExampleServiceImplTest):
Unfinished stubbing detected here:
-> at com.example.service.impl.ExampleServiceImplTest.prepareScheduleChangePreconditions(ExampleServiceImplTest.java:134)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!

方法不是最终的。任何帮助或线索都将不胜感激。

更新1

根据Mike B的请求,我成功地将其隔离到在Java 7中失败的更简单的测试用例中。

@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {

    @Mock
    Program program;

    private void preparePreconditions() {
        Client client = mock(Client.class);
        when(client.getPrograms()).thenReturn(new TreeSet<Program>(Collections.singleton(program)));
    }

    public static class Client {
        public SortedSet<Program> getPrograms() {
            return new TreeSet<Program>();
        }
    }

    public static class Program implements Comparable<Program> {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public int compareTo(Program program) {
            return 0;
        }
    }

    @Test
    public void test() {
        preparePreconditions();
    }

}

更新2

奇怪的是,如果我这样做的话,它会起作用:

TreeSet<Program> programs = new TreeSet<Program>();
programs.add(program);
when(client.getPrograms()).thenReturn(programs);

共有2个答案

韶镜
2023-03-14

这实际上并不能回答你的问题,但请记住嘲弄的基本指令:

  1. 模拟角色,而不是对象

实际上,这意味着嘲笑类(即不是接口)是闪烁的红色警告信号,表明您的设计有问题。

如果您无法控制与之接口的代码(例如,它是第三方库或遗留软件),我喜欢将类包装在接口中并模拟它。作为一个额外的好处,这也允许您在其他代码中重命名名称不佳的方法(和类)。从您的示例中,客户端返回哪些“程序”?是活动程序集,正在运行的程序,还是什么?让我们假设它是活动程序集:

public interface Programs {
    SortedSet<Program> active();
}

class SimpleClientWrapper implements Programs {
    private final Client wrapped;

    SimpleClientWrapper(Client c) { wrapped = c; }

    public SortedSet<Program> active() { return wrapped.getPrograms(); }
}

如果这感觉工作太多(我承认有时这是过度的),另一种可能性,如果你想模拟的方法不是最终的,是在你的测试中暂时覆盖它们:

Client client = new Client() {
    @Override
    public SortedSet<Program> getPrograms() {
        return new TreeSet<Program>(Collections.singleton(program));
    }
};

我有时会使用这种方法来重写错误处理程序等。

欧阳楚
2023-03-14

我相信这里真正发生的是在(…)的情况下,在单个中调用多个模拟方法。然后(…) 语句。

考虑下面的例子:

when(program.getName()).thenReturn(String.valueOf(program.compareTo(null)));

它返回与您相同的异常。这是因为在mock上调用了两个方法:getName()compareTo()在singlewhen(…)中。然后返回(…) 语句。

在本页(mockito文档)中,您还可以阅读:

默认情况下,对于返回值的所有方法,mock返回null、空集合或适当的基元/基元包装值(例如:0、false、...对于int/intger、boolean/Boolean、...)。

因此,mockito必须有某种机制来检测对某个被模拟对象的哪个调用要做什么(返回)。

在您的示例中,第二次调用由new TreeSet进行

TreeSet的实现似乎从Java6变成了Java7。这就是为什么它本可以更早起作用。

 类似资料:
  • 问题内容: 它说 您的SQL语法有误;检查与您的MySQL服务器版本相对应的手册以获取正确的语法,以在第4行“ airlines.iaco_code = airport.iaco_code完全外部联接”附近使用 语法对我来说似乎正确。我以前从未做过很多联接,但是我需要一个表中的那些列,这些列被各种ID交叉引用。 问题答案: MySQL中没有。见7.2.12。外连接简化和12.2.8.1。JOIN语

  • 我是JMeter的新手,我正在尝试让JMeter为现有的测试脚本生成html报告仪表板。我在处理过程中没有收到任何异常,并且日志指示生成报告时没有问题: 但是,当我查看生成的索引.html文件时,没有数据: 结果.csv文件不为空: 我的报告生成器和保存服务配置是: 我试图搜索类似的问题(在这里和其他地方),但我找不到任何解决这种情况的东西。结果正在以我期望的格式写入CSV文件并填充,但是在读取数

  • 本文向大家介绍缺陷报告的用途是什么?相关面试题,主要包含被问及缺陷报告的用途是什么?时的应答技巧和注意事项,需要的朋友参考一下 ①记录缺陷 ②缺陷分类 ③缺陷跟踪

  • 错误日志对于发现程序中的错误是非常有帮助的,但是有些时候它也会将应用程序的结构暴露给外部。为了有效的保护你的应用程序不受到由此而引发的问题。你需要将在你的服务器上使用开发和生产(线上)两套不同的配置。 开发环境 为了在开发环境中显示所有可能的错误,将你的 php.ini 进行如下配置: display_errors = On display_startup_errors = On error_re

  • 由于某种原因,jar在TypeSafe的bintray中不再可用。最大的版本是0.13.9。 我知道获取它的地方是https://repo.typesafe.com/typesafe/ivy-release/,但是我如何告诉sbt使用这个回购呢? 我已经试过: null 如何告诉sbt在哪里获取二进制文件?

  • 我正在尝试使用JUnit错误收集器报告错误。虽然我的断言失败了,但JUnit中并没有报告错误。但我在控制台中收到了“错误”信息。