我已经实现了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: Address already in use: JVM_Bind
。
这意味着该端口仍在使用,因此我猜我的stopServer()
不正确。我出了什么问题?
请注意,如果我在调用方法registry.list()
之前和之后使用stopServer()
方法,我会看到:
BEFORE: foobar
AFTER: (nothing)
编辑:
我还修改了stopServer()
关于解释here的解决方案:
public void stopServer() {
try {
registry.unbind("foobar");
UnicastRemoteObject.unexportObject(myRemoteObject, true);
} catch (Exception e) {
e.printStackTrace();
}
}
但它并没有解决我的问题...
答案 0 :(得分:1)
我遇到了同样的问题并最终修改了我的服务器代码,因此start方法基本上就是这样(在捕获之后注意调用getRegistry
和rebind
如果它已经存在,它将返回注册表:
public void startServer() {
try {
...
registry = LocateRegistry.createRegistry(serverPort);
} catch (RemoteException e) {
}
LocateRegistry.getRegistry(port);
registry.rebind("foobar", myRemoteObject);
}
答案 1 :(得分:0)
首先,我倾向于避免空的异常块,即使在“不可能发生”的情况下也是如此。
try {
socket.close();
} catch (IOException e2) {
}
可以肯定的是那里有一个例外。
我(相当疯狂)的猜测是,你可能有时间问题。也许网络基础设施需要很短的时间才能注意到套接字已关闭。在最终断言修复之前,是否会睡一两秒?
答案 2 :(得分:0)
我认为您需要取消导出注册表。尝试:
public void stopServer() {
try {
registry.unbind("foobar");
UnicastRemoteObject.unexportObject(registry, true);
} catch (Exception e) {
e.printStackTrace();
}
}
但是,one source声称在JVM退出之前无法释放端口。我不知道这是不是真的(没有尝试过),但是取消注册表是朝着正确方向迈出的一步。