gpt4 book ai didi

java - 如何正确模拟可自动关闭的资源?

转载 作者:搜寻专家 更新时间:2023-10-31 19:29:03 24 4
gpt4 key购买 nike

我正在尝试为此编写一个单元测试:

try (final DatagramChannel channel = helper.createChannel()) {

...

}

在我的测试中,我模拟了助手(使用 Mockito),并告诉 helper.createChannel() 返回一个模拟的 channel 。

这个测试失败了

java.lang.NullPointerException
at java.nio.channels.spi.AbstractInterruptibleChannel.close(AbstractInterruptibleChannel.java:111)

我了解 Java 中的 try-with-resources 设施在退出 try block 时调用 DatagramChannel 中的 close() 方法,但不应该调用模拟 DatagramChannel 中的 close() 方法吗?

调试器告诉我 AbstractInterruptibleChannel 中的 closeLock 为 null。

我应该将 DatagramChannel 子类化,覆盖其中的 close() 方法,然后模拟我的子类吗?或者,我是否以更深刻的方式做错了什么(辅助模拟返回模拟)?

问候,弗雷德里克·以色列森

测试代码,根据要求:

@Mock
private InetAddress peerAddress;
@Mock
private UDPChannelHelper helper;
@Mock
private DatagramChannel channel;

private UDPTransportImpl transport;

@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(helper.createChannel()).thenReturn(channel);
transport = new UDPTransportImpl(peerAddress, 0, helper);
}

@Test
public void testNormalSubmit() throws Exception {
transport.submit("Hello");
}

如您所见,我没有为 channel.close() 指定任何行为。我相信我不必这样做,因为 close() 返回 void。

最佳答案

您正在模拟一个真正的类 DatagramChannel,它扩展了 AbstractInterruptibleChannel。但是 AbstractInterruptibleChannel.close 是最终的,Mockito 目前无法模拟最终代码。这解释了为什么代码中有 NPE。

我必须提醒您,人们普遍认为模拟您不拥有的类型是不好的做法。我见过有人这样做,多年后当真正的实现发生变化时,他们大吃一惊,但模拟行为并没有发生变化,因此他们错误地认为在更新库版本时一切正常。

不过,如果你想继续这种方式,因为你有充分的理由(并且有一些),你可以返回一个接口(interface)的模拟,比如实际扩展 Channel可关闭。或者您可以使用您需要与之交互的任何其他接口(interface),这些接口(interface)存在于 DatagramChannel 中。此外,如果您需要多个接口(interface),只需使用 mock(Channel.class, withSetting().extraInterfaces(...))

希望对你有帮助干杯,布莱斯

关于java - 如何正确模拟可自动关闭的资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15131105/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com