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

时间:2013-05-12 20:17:35

标签: 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;
    }
    return result;
}

问题是,getLocalPort()在真实系统端口上运行,在测试期间,它会根据本地系统进行传递。

测试此类方法的有效方法是什么?

4 个答案:

答案 0 :(得分:3)

ServerSocket实例应该可以通过工厂获得,(工厂)passed as a dependency到您的班级:

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

// ...
ServerSocket ss = this.socketFactory.GetServerSocket(port.getPortNumber());
ss.getLocalPort();
ss.close();

然后,在您的单元测试中,您可以mock socketFactory返回虚假服务器套接字,从而将其与任何真实世界系统“断开连接”。

请注意,ServerSocket可能还需要是抽象(例如,由接口/基类表示),因此它也可以被模拟。

答案 1 :(得分:1)

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

您的测试需要这些注释:

@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

答案 2 :(得分:0)

你需要考虑模拟出serverSocket类。

使用当前代码,新调用会使测试变得困难。

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

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

答案 3 :(得分:-1)

你可以写

public boolean isFree(LdapPort port) {
    try{
        new ServerSocket(port.getPortNumber()).close();
        return true;
    } catch(IOException ex){
        return false;
    }
}

您可以通过在同一端口上创建ServerSocket来测试它,并且isFree应该为false,然后关闭ServerSocket并且isFree应该为true。