【发布时间】:2016-12-16 13:20:16
【问题描述】:
基本上我有一个 Java 类,它在套接字通道上执行选择,我想存根通道以便我可以测试选择是否按预期工作。
例如,被测试的类大致是这样做的:
class TestedClass {
TestedClass(SocketChannel socket) { this.socket = socket }
// ...
SocketChannel socket;
// ...
void foo() {
// Wait a while for far end to close as it will report an error
// if we do it. But don't wait forever!
// A -1 read means the socket was closed by the other end.
// If we select on a read, we can check that, or time out
// after a reasonable delay.
Selector selector = Selector.open();
socket.configureBlocking(false);
socket.register(selector, SelectionKey.OP_READ);
while(selector.select(1000) == 0) {
Log.debug("waiting for far end to close socket...")
}
ByteBuffer buffer = ByteBuffer.allocate(1);
if (socket.read(buffer) >= 0) {
Log.debug("far end didn't close");
// The far end didn't close the connection, as we hoped
abort(AbortCause.ServerClosed);
}
Log.debug("far end closed");
}
}
我希望能够测试这样的东西:
def "test we don't shut prematurely" () {
when:
boolean wasClosedPrematurely
SocketChannel socket = Stub(@SocketChannel) {
// insert stub methods here ....
}
TestedClass tc = new TestedClass(socket)
tc.foo();
then:
wasClosedPrematurely == false
}
这是基于一个真实的例子,但细节并不重要。总体目标是如何对支持选择的 SocketChannels 进行存根,这样我就不必创建一个真实的客户端来进行测试。
我也知道它比仅存根 SocketChannel 更复杂:似乎我需要拦截 Selector.open() 或以某种方式提供自定义系统默认 SelectorProvider。如果我只是简单地存根 SocketChannel,当我尝试将通过 Selection.open() 获得的选择器注册到我的存根时,我会得到一个 IllegalSelectorException,不幸的是,基本的 AbstractSelectableChannel#register 方法是最终的。
但是我找不到任何有用的指示来说明 Spock Mocks 如何或是否可以实现这一点,而且这似乎是一件很常见的事情,所以在这里提出一个很好的问题。有人可以帮忙吗?
【问题讨论】:
标签: java unit-testing spock socketchannel