拦截传出的HTTP请求

时间:2016-02-05 11:28:09

标签: java api unit-testing http proxy

所以我正在寻找一个库或某种方式拦截来自我的Java应用程序的任何传出HTTP请求?为什么?因为我想对API集成进行单元测试,并且因为我使用了该API的库(包装器),所以我无法修改它的任何代码。我的代码不是实际发出HTTP请求的。

因此,根据API的文档,我需要拦截它们,查看它们并断言它们是正确的。

我试过在网上看,但我找不到我正在寻找的确切内容。大多数图书馆都允许我这样做,只有我自己正确配置了请求,但我不能这样做,因为它们是由API包装器而不是我的代码创建的。

干杯

P.S一些示例代码

String path = "/some/path";
String repoOwner = "John Doe";
String repoName = "John repo"

GitHubClient client = new GitHubClient();
client.setCredentials(this.username, this.password);

RepositoryService repositoryService = new RepositoryService(client);
CommitService commitService = new CommitService(client);

Repository repo = repositoryService.getRepository(repoOwner, repoName);

List<RepositoryCommit> commits = commitService.getCommits(repo, null, path);

这将使用API​​包装器获取给定存储库中的所有提交。假设我想查看此代码正在进行的HTTP请求,然后我想对它们进行单元测试并断言它们是正确的。我该怎么办?有没有办法拦截它们,抓住它们有点像异常,并用它们做些什么,比如断言?

1 个答案:

答案 0 :(得分:0)

你要做的事情并不容易,而且从我的观点来看,它并没有多大意义。

您正在尝试测试您的应用但主要是您尝试测试GitHubClient库

如果我是你,我会在你的测试中只使用模拟并验证输入参数。所以测试就像这样(使用mockito):

List<RepositoryCommit> commits = new ArrayList<>();
commits.add(new RepositoryCommit(....));
commits.add(new RepositoryCommit(....));
when(commitService.getCommits(repo, null, path)).thenReturn(commits);

这样你就可以避免进行库测试。

如果你想真正调查一下这个库的功能 - 它发送了什么请求以及发生了什么 - 我建议你查看库代码,找到实际请求的地方设置并在调试模式下运行您的应用程序并在那里添加断点

如果您真的想要处理(例如,记录,复制......)即使在生产中对GitHub的真实请求,您也可以使用AspectJ。这将改变字节代码,以便您可以包装特定的方法调用。再一次,您必须在GitHub库中找到执行真正的GitHub(我假设HTTP)调用的位置,并将方面附加到该调用。在方面,您基本上声明要拦截哪种方法以及在调用之前或之后要执行的操作。我并不是这方面的专家,所以我无法向您提供更多信息 - 有关于方面的教程 - https://eclipse.org/aspectj/doc/next/progguide/starting.html

其他选项也是安装一些网络监视工具,如wireshark

修改

如何避免代价高昂的GitHub调用的其他选项是创建一个这样的简单包装器:

public class GitHubServiceImpl implements GitHubService {
    private Rpository repo;

    /** other methods **/

    @Override
    public List<RepositoryCommit> getAllCommits(String path) {
        return commitService.getCommits(repo, null, path));
    }
}

这是您要测试的实际服务。

public class CommitService {

    private GitHubService gitHubService;

    private String path;

    public List<RepositoryCommit> getAll() {
        return gitHubService.getAllCommits(path);
    }

}

并且对于集成测试,创建GitHubService接口的特殊实现:

public class TestGitHubService implements GitHubService {

    private Map<String, RepositoryCommit> preArrangedCommits;
    /** other methods **/

    public void setPreArrangedCommits(Map<String, RepositoryCommit> preArrangedCommits) {
        this.preArrangedCommits = preArrangedCommits;
    }

    @Override
    public List<RepositoryCommit> getAllCommits(String path) {
        return preArrangedCommits;
    }
}

并在测试电话中:

public class CommitServiceIntegrationTest {
    // @Autowired, @Bean maybe?
    private CommitService commitService;

    // @Autowired, @Bean maybe?
    private GitHubService gitHubService;

    public void testGetAll() {
        Map<String, RepositoryCommit> preArrangedCommits = new HashMap<>();
        preArrangedCommits.put("path/", new RepositoryCommit(...));
        gitHubService.setPreArrangedCommits(preArrangedCommits);
        List<RepositoryCommit> commits = commitService.getAll();
        assertEquals(commits, preArrangedCommits);
    }
}

我会这样走。