我们如何为 Socket 连接编写测试用例
Posted
技术标签:
【中文标题】我们如何为 Socket 连接编写测试用例【英文标题】:How can we write test cases for Socket connections 【发布时间】:2022-01-17 23:32:37 【问题描述】:下面是代码sn-p,必须测试Socket连接的真假场景。
public boolean pingHost(String hostname, int port)
try (Socket socket = new Socket())
socket.connect(new InetSocketAddress(hostname, port), 3000);
return true;
catch (IOException e)
return false;
【问题讨论】:
【参考方案1】:这是模拟的标准用例。使用 PowerMock,即您可以模拟构造函数调用并返回一个模拟对象。您还可以在构造函数调用中验证正确的参数。只需搜索“Powermock 模拟构造函数”。 如果您无法选择模拟,则另一种选择是使用可用于 *NIX 和 Windows 平台的 netcat 侦听端口。
编辑 2021.12.16 -----------------
您需要包含这四个罐子才能使用 Mockito 和 PowerMock (Maven pom)
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.1.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-inline -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.1.0</version>
<scope>test</scope>
</dependency>
<!-- https://www.baeldung.com/intro-to-powermock -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
但是有很多关于如何设置 Mockito 和 PowerMock 的文档。
这是一个带有一些注释的可运行示例,让您了解如何使用模拟进行测试。
package __scratchpad__;
import static org.junit.Assert.fail;
import static org.powermock.api.mockito.PowerMockito.whenNew;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(PingerTest.Pinger.class)
public class PingerTest
// Inner class just to have a compact 'all in one' example
public class Pinger
// refactored to better coding style (avoid 'Magic numbers')
// AND for testability because TIM-OUT is now accessible for test
public static final int TIME_OUT = 3000;
public boolean pingHost(String hostname, int port)
try (Socket socket = new Socket())
socket.connect(new InetSocketAddress(hostname, port), TIME_OUT);
return true;
catch (IOException e)
return false;
@Test
public void testPingHost()
// create required mock objects to inject
InetSocketAddress addressMock = Mockito.mock(InetSocketAddress.class);
Socket socketMock = Mockito.mock(Socket.class);
// create parameters
final String hostname = "answer.deepthought";
final int port = 42;
final int timeOut = PingerTest.Pinger.TIME_OUT;
// create class under test
Pinger pingerUnderTest = new Pinger();
try
// mock constructor call of class InetSocketAddress and verify correct parameters
// If parameters of call are different to the expected, than NO mock object is returned, the test will fail
// Otherwise the addressMock object is returned
whenNew(InetSocketAddress.class)
.withArguments(hostname, port)
.thenReturn(addressMock);
// mock constructor call of Socket class
whenNew(Socket.class)
.withNoArguments()
.thenReturn(socketMock);
// call method under test with parameters defined earlier.
// If parameters are different to them of InetSocketAddress constructor call the test will fail.
pingerUnderTest.pingHost(hostname, port);
// if all works fine exactly one call to method connect() with specified parameters MUST appear
// if there are more or less calls or any of the parameters is different, than the test will fail
Mockito.verify(socketMock).connect(addressMock, timeOut);
catch(Exception e)
e.printStackTrace();
fail("Unexpected exception caught!");
【讨论】:
能否请您至少提供一个高级代码。以上是关于我们如何为 Socket 连接编写测试用例的主要内容,如果未能解决你的问题,请参考以下文章