Java 使用ServerSocket类对方法进行单元测试的最佳方法是什么?

Java 使用ServerSocket类对方法进行单元测试的最佳方法是什么?,java,unit-testing,junit,mocking,serversocket,Java,Unit Testing,Junit,Mocking,Serversocket,我有这样一种方法: public boolean isFree(LdapPort port) { boolean result = false; try{ ServerSocket ss = new ServerSocket(port.getPortNumber()); ss.getLocalPort(); ss.close(); } catch(IOException ex){ result = true;

我有这样一种方法:

public boolean isFree(LdapPort port) {
    boolean result = false;
    try{
        ServerSocket ss = new ServerSocket(port.getPortNumber());
        ss.getLocalPort();
        ss.close();
    } catch(IOException ex){
        result = true;
    }
    return result;
}
问题是,
getLocalPort()
在实际系统端口上运行,并且在测试过程中根据本地系统通过


测试这种方法的有效方法应该是什么?

您需要研究模拟serverSocket类

对于您当前的代码,新的调用使得测试变得困难

将serversocket的实例注入到方法/类中 然后可以注入一个模拟实例进行测试


我总是发现一个很好的模拟框架

使用PowerMock可以模拟构造函数。 因此,对要模拟的类的匹配构造函数的所有调用都可以返回一个模拟实例,您将在测试中准备该实例

您的测试将需要以下注释:

@RunWith(PowerMockRunner.class)
@PrepareForTest( ServerSocket.class )
然后在试验方法中:

ServerSocket ssMock = createMock(ServerSocket.class);

expectNew(ServerSocket.class, port.getPortNumber()).andReturn(ssMock); // so constructor of the ServerSocket class taking this specific port number will return the ssMock instance

expect(ssMock.getLocalPort()).andReturn(10); // when method getLocalPort is invoked return 10

reply(ssMock, ServerSocket.class); // do not forget to specify not only the mock instance (ssMock) but the ServerSocket class as well

ServerSocket
实例应该可以通过factory获得,该(factory)适用于您的类:

// Passing factory dependency via constructor injection
public PortChecker(IServerSocketFactory socketFactory)
{
    this.socketFactory = socketFactory;
}

// ...
ServerSocket ss = this.socketFactory.GetServerSocket(port.getPortNumber());
ss.getLocalPort();
ss.close();
然后,在单元测试中,您可以
socketFactory
返回假服务器套接字,从而将其与任何真实系统“断开”

请注意,
ServerSocket
可能还需要是抽象的(比如,由接口/基类表示),这样它也可以被模拟

public boolean isFree(LdapPort port) {
    try{
        new ServerSocket(port.getPortNumber()).close();
        return true;
    } catch(IOException ex){
        return false;
    }
}
您可以通过在同一端口上创建ServerSocket来测试它,isFree应该为false,然后关闭ServerSocket,isFree应该为true