对 RMI 服务器的停止方法进行单元测试时出现问题
我已经实现了一个 RMI 服务器,现在我想使用 JUnit 测试来测试启动和停止该服务器的方法是否正确实现。
下面是我的 RMI 服务器的(简化的)代码:
public void startServer() {
try {
...
registry = LocateRegistry.createRegistry(serverPort);
registry.rebind("foobar", myRemoteObject);
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopServer() {
try {
registry.unbind("foobar");
} catch (Exception e) {
e.printStackTrace();
}
}
现在,我想做一个 JUnit 测试来检查 startServer()
和 stopServer()
是否正常工作。
因此,我实现了这个简单的 JUnit 测试:
private boolean isRunning(int port) {
boolean portTaken = false;
ServerSocket socket = null;
try {
socket = new ServerSocket(port);
// If we have succesfully created the ServerSocket, then it means that the port is available...
} catch (IOException e) {
portTaken = true;
if (socket != null) {
try {
socket.close();
} catch (IOException e2) {
}
}
}
return portTaken;
}
@Test
public void testStartAndStopServer() {
MyRMIServer server = new MyRMIServer();
assertNotNull(server);
int port = server.getServerPort();
assertTrue(port != -1);
// Check if the current server is NOT running.
assertFalse(isRunning(port));
// Start the server and then check if it is running.
server.startServer();
assertTrue(isRunning(port));
// Now stop the server...
server.stopServer();
assertFalse(isRunning(port));
}
我的问题是最后一个断言无效。如果我在方法 isRunning()
中打印堆栈跟踪,则会收到错误 java.net.BindException:地址已在使用中:JVM_Bind
。
这意味着该端口仍在使用,因此我猜测我的 stopServer()
不正确。我做错了什么?
请注意,如果我在调用方法 stopServer()
之前和之后使用 registry.list()
方法,我会看到:
BEFORE: foobar
AFTER: (nothing)
编辑:
我还修改了我的 stopServer()
关于此处解释的解决方案:
public void stopServer() {
try {
registry.unbind("foobar");
UnicastRemoteObject.unexportObject(myRemoteObject, true);
} catch (Exception e) {
e.printStackTrace();
}
}
但这并没有解决我的问题...
I have implemented a RMI Server and now I wanted to test if the method to start and stop this server are correcly implemented, using a JUnit test.
Here is the (simplified) code of my RMI server:
public void startServer() {
try {
...
registry = LocateRegistry.createRegistry(serverPort);
registry.rebind("foobar", myRemoteObject);
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopServer() {
try {
registry.unbind("foobar");
} catch (Exception e) {
e.printStackTrace();
}
}
Now, I want to make a JUnit test to check if the startServer()
and stopServer()
are correctly working.
Thus, I've implemented this simple JUnit test:
private boolean isRunning(int port) {
boolean portTaken = false;
ServerSocket socket = null;
try {
socket = new ServerSocket(port);
// If we have succesfully created the ServerSocket, then it means that the port is available...
} catch (IOException e) {
portTaken = true;
if (socket != null) {
try {
socket.close();
} catch (IOException e2) {
}
}
}
return portTaken;
}
@Test
public void testStartAndStopServer() {
MyRMIServer server = new MyRMIServer();
assertNotNull(server);
int port = server.getServerPort();
assertTrue(port != -1);
// Check if the current server is NOT running.
assertFalse(isRunning(port));
// Start the server and then check if it is running.
server.startServer();
assertTrue(isRunning(port));
// Now stop the server...
server.stopServer();
assertFalse(isRunning(port));
}
My problem is that the last assert is not valid. If I print the stacktrace in the method isRunning()
, I get the error java.net.BindException: Address already in use: JVM_Bind
.
This means that the port is still used so I guess that my stopServer()
is not correct. What did I get wrong?
Note that if I use the registry.list()
method before and after calling my method stopServer()
, I see:
BEFORE: foobar
AFTER: (nothing)
Edit:
I've also modified my stopServer()
regarding a solution explained here:
public void stopServer() {
try {
registry.unbind("foobar");
UnicastRemoteObject.unexportObject(myRemoteObject, true);
} catch (Exception e) {
e.printStackTrace();
}
}
but it doesn't solve my problem...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我遇到了同样的问题,最终修改了我的服务器代码,以便启动方法基本上看起来像这样(注意对
getRegistry
和rebind
after 如果注册表已经存在,则将取回注册表):I had the same problem and ended up modifying my server code so that the start method would basically look like (notice the call to
getRegistry
andrebind
after the catch which will get back the registry if it was already there):首先,我倾向于避免空异常块,即使在“不可能发生”的情况下也是如此。
可以想象,那里有一个例外。
我(相当疯狂)的猜测是,你可能遇到了时间问题。也许网络基础设施需要很短的时间才能注意到套接字已关闭。在最终断言之前睡一两秒可以修复它吗?
First, I would tend to avoid empty exception blocks, even in "can't happen" cases.
just concenvably there's an exception there.
My (rather wild) guess, is that you might have a timing problem. Perhaps the network infrastructure takes a short time to notice that the socket is closed. Does sleeping for a second or two before the final assert fix it?
我认为您需要取消导出注册表。尝试:
但是,一个来源声称在 JVM 退出之前无法释放端口。我不知道这是否属实(没有尝试过),但取消导出注册表是朝着正确方向迈出的一步。
I think you need to unexport the registry. Try:
However, one source claims you cannot free up the port until the JVM exits. I don't know if that's true or not (haven't tried it), but unexporting the registry is a step in the right direction.