Spring Boot 模拟的ClosebleHttpClient正在发送真实的的POST请求

yzuktlbb  于 2022-11-23  发布在  Spring
关注(0)|答案(1)|浏览(172)

我有一个Sping Boot 类的单元测试,当我运行测试时,它将一个文件发送到带有POST请求的URL,它将实际请求发送到真实的的URL。我认为ClosebleHttpClient没有被嘲笑。

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;
    }
}

有没有办法只重构测试来解决这个问题。

des4xlb0

des4xlb01#

你这里有很多问题:
您正在使用@InjectMocks(用于向测试主题的构造函数注入mock,在您的服务中,此函数只接受一个参数,因此其他参数不被注入)。同时,您将其手动添加到测试方法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);

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

相关问题