【问题标题】:Mocked CloseableHttpClient is sending real POST request模拟的 CloseableHttpClient 正在发送真实的 POST 请求
【发布时间】:2022-11-18 16:32:51
【问题描述】:

我有一个针对 Spring Boot 类的单元测试,当我运行测试时,它会使用 POST 请求将文件发送到 URL,它会将实际请求发送到真实的 url。我认为 CloseableHttpClient 没有被嘲笑。

class FileSenderTest {
    @InjectMocks
    FileSender fileSender;
    
    @Mock
    UrlConfig urlConfig;
    
    @Mock
    InetAddress inetAddress;

    @Mock
    SSLContextFactory sslContextFactory = new SSLContextFactory();

    @BeforeEach
    void setUp() {
    }

    @AfterEach
    void tearDown() {
    }
   
    @Test
    public void postData() throws Exception {
        URL url = new URL("/someUrl");
        urlConfig.setURL(url);
        urlConfig.setPassword("somePassword123");
        fileSender = new FileSender(urlConfig);

        URL res = getClass().getClassLoader().getResource("test.json");
        File file = Paths.get(res.toURI()).toFile();
        String filePath = file.getAbsolutePath();
        
        HttpPost httpPost = mock(HttpPost.class);
        StatusLine statusLine = mock(StatusLine.class);
        CloseableHttpClient closeableHttpClient = mock(CloseableHttpClient.class);
        CloseableHttpResponse closeableHttpResponse = mock(CloseableHttpResponse.class);

        when(statusLine.getStatusCode()).thenReturn(200);
        when(closeableHttpResponse.getStatusLine()).thenReturn(statusLine);
        when(closeable.HttpClient.execute(httpPost)).thenReturn(closeableHttpResponse);

        int response = fileSender.sendFile(filePath);

        Assertions.assertEquals(200, response);
    }

}

这是要测试的类:

@Service 
public class FileSender {
    private final UrlConfig urlConfig;
    SSLContext sslContext;
    
    @Autowired
    public FileSender(UrlConfig urlConfig) {
        this.urlConfig = urlConfig;
    }

    public int sendFile(String targetFileName) throws IOException {
        Path tracesPath = Paths.get(targetFileName);
        HttpPost httpPost = new HttpPost(this.UrlConfig.getURL().toString());
        httpPost.addHeader("Accept", "application/json");

        MultipartEntityBuilder builder = MultipartEntityBuilder.create();        
        builder.addBinary("file", new ByteArrayInputStream(Files.readAllBytes(tracesPath)), ContentType.APPLICATION_OCTET_STREAM, targetFileName);

        HttpEntity multipart = builder.build();
        httpPost.setEntity(multipart);
        
        sslContext = this.UrlConfig.getSSLContext();
        sslContext = SSLContextFactory.create().this.urlConfig.setSSLContext(sslContext);

       try (CloseableHttpClient httpClient = HttpClients.custom()setSSLContext(sslContext).build);
           CloseableHttpResponse response = httpClient.execute(httpPost)) {
               return response.getStatusLine().getStatusCode();
        }  catch (IOException e) {
               log.error(e);
        }
        return 500;
    }
}

有什么办法可以解决仅重构测试的问题。

【问题讨论】:

    标签: java spring-boot mockito


    【解决方案1】:

    你在这里有很多问题:

    您正在使用 @InjectMocks(用于将模拟注入到测试对象的构造函数中,在您的服务中,该参数仅采用一个参数,因此不会注入其余参数)。同时,您在测试方法 fileSender = new FileSender(urlConfig); 中手动添加它,这是多余的(我可能建议您删除注释并使用测试方法内部的注释,因为您在那里设置 urlConfig)。

    如前所述,您没有注入以下任何模拟,因为 FileSender 构造函数仅将 urlConfig 作为参数。如果你想用你声明的模拟实例化FileSender,你需要创建一个额外的构造函数,将它们作为参数。

    @Mock SSLContextFactory sslContextFactory = new SSLContextFactory();
    @Mock InetAddress inetAddress;
    HttpPost httpPost = mock(HttpPost.class);
    StatusLine statusLine = mock(StatusLine.class);
    CloseableHttpClient closeableHttpClient = mock(CloseableHttpClient.class);
    CloseableHttpResponse closeableHttpResponse = mock(CloseableHttpResponse.class);
    

    您在测试对象中也有许多静态调用,由于它们与各自的类紧密耦合,因此很难模拟。您可能需要弄清楚如何处理这些调用中的每一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 2021-03-12
      相关资源
      最近更新 更多