简体   繁体   English

如何正确监视输入 stream

[英]How to properly spy on an input stream

My understanding is, that Mockito.spy(object) wraps a proxy around an existing object.我的理解是, Mockito.spy(object)将代理包装在现有的 object 周围。 This proxy delegates the method calls to the spied object and allows further verification (So it's different to a mock which provides no implementation).此代理将方法调用委托给间谍 object 并允许进一步验证(因此它与不提供实现的模拟不同)。

I want to spy on an input stream to ensure the close/read methods are properly called.我想监视输入 stream 以确保正确调用关闭/读取方法。 But the following (simple) spy code doesn't work:但是以下(简单)间谍代码不起作用:

// Create a spy input stream object
String testData = "Hello";
InputStream inputStream = new ByteArrayInputStream(testData.getBytes(StandardCharsets.UTF_8));
InputStream spiedInputStream = spy(inputStream);
assertEquals(testData.getBytes(StandardCharsets.UTF_8).length, spiedInputStream.available()); // Fails: Expected 5, Actual 0

// Read the input stream
byte [] readData = new byte[testData.length()];
assertEquals(testData.getBytes(StandardCharsets.UTF_8).length, spiedInputStream.read(readData)); // Fails: Expected 5, Actual -1
assertEquals(testData, new String(readData, StandardCharsets.UTF_8)); // Fails, readData is fully zeroed

So what am I doing wrong (Ubuntu 22.04, Java 17, Mockito 4.7.0)那么我做错了什么(Ubuntu 22.04,Java 17,Mockito 4.7.0)

The behaviour you described is reproducible on the following configuration:您描述的行为可在以下配置上重现:

  • mockito-core模拟核心
  • JDK 17 JDK 17

The simplest way for you to proceed is to switch to mockito-inline.最简单的方法是切换到 mockito-inline。

In case of mockito-core and JDK 17, the fields in the spy are not properly initialized:在 mockito-core 和 JDK 17 的情况下,spy 中的字段未正确初始化:

public ByteArrayInputStream(byte buf[]) {
    this.buf = buf;
    this.pos = 0;
    this.count = buf.length;
}

The count variable should be equal to buf.length, but in the spy it is set to 0. count 变量应该等于 buf.length,但在 spy 中它被设置为 0。

The problem stems from the fact that subclass mock maker is fundamentally limited on JDK17, mockito team seems to be aware of the problem and even considers switching to inline mock maker as default on JDK 17:问题源于子类 mock maker 从根本上受限于 JDK17,mockito 团队似乎意识到了这个问题,甚至考虑在 JDK 17 上默认切换到 inline mock maker:

Switch the default mockmaker to the inline mockmaker on JDK 17+ #2589 :将默认的 mockmaker 切换到 JDK 17+ #2589 上的内联 mockmaker

TLDR: more and more use cases are broken (by default) with Mockito and JDK 17. That's because the subclass mockmaker runs into fundamental limitations on JDK 17, but the inline mockmaker works as expected. TLDR:越来越多的用例被 Mockito 和 JDK 17 破坏(默认情况下)。这是因为子类 mockmaker 在 JDK 17 上遇到了基本限制,但内联 mockmaker 可以按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM