我们如何为 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 连接编写测试用例的主要内容,如果未能解决你的问题,请参考以下文章

如何为登录屏幕ios swift编写测试用例?

如何为委托方法编写 GHunit 测试用例?

如何为更长的网页编写 UI 手动测试用例?

如何为 JWT 策略编写单元测试用例

如何为以下代码段编写单元测试用例

如何为 Spring 托管 bean 编写 Junit 测试用例?