对 RMI 服务器的停止方法进行单元测试时出现问题

发布于 2024-08-04 09:23:45 字数 2362 浏览 2 评论 0原文

我已经实现了一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

嘴硬脾气大 2024-08-11 09:23:45

我遇到了同样的问题,最终修改了我的服务器代码,以便启动方法基本上看起来像这样(注意对 getRegistryrebind after 如果注册表已经存在,则将取回注册表):

public void startServer() {
    try {
        ...
        registry = LocateRegistry.createRegistry(serverPort);
    } catch (RemoteException e) {
    }
    LocateRegistry.getRegistry(port);
    registry.rebind("foobar", myRemoteObject);  
}

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 and rebind after the catch which will get back the registry if it was already there):

public void startServer() {
    try {
        ...
        registry = LocateRegistry.createRegistry(serverPort);
    } catch (RemoteException e) {
    }
    LocateRegistry.getRegistry(port);
    registry.rebind("foobar", myRemoteObject);  
}
云雾 2024-08-11 09:23:45

首先,我倾向于避免空异常块,即使在“不可能发生”的情况下也是如此。

  try {
            socket.close();
  } catch (IOException e2) {
  }

可以想象,那里有一个例外。

我(相当疯狂)的猜测是,你可能遇到了时间问题。也许网络基础设施需要很短的时间才能注意到套接字已关闭。在最终断言之前睡一两秒可以修复它吗?

First, I would tend to avoid empty exception blocks, even in "can't happen" cases.

  try {
            socket.close();
  } catch (IOException e2) {
  }

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?

迷你仙 2024-08-11 09:23:45

我认为您需要取消导出注册表。尝试:

public void stopServer() {
    try {
        registry.unbind("foobar");
        UnicastRemoteObject.unexportObject(registry, true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

但是,一个来源声称在 JVM 退出之前无法释放端口。我不知道这是否属实(没有尝试过),但取消导出注册表是朝着正确方向迈出的一步。

I think you need to unexport the registry. Try:

public void stopServer() {
    try {
        registry.unbind("foobar");
        UnicastRemoteObject.unexportObject(registry, true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文