如何为网络客户端编写单元测试?

12

我需要编写一个简单的HTTP客户端。为我的类编写单元测试将是很好的事情。但我不知道如何编写适当且可测试的类。

例如,我有一个像这样的客户端:

class HTTPClient
{
public:
     HTTPCLient(const std::string& host, const std::string& port): session(host, port) {}

     void send()
     {
         session.sendRequest(someRequest);
         Response response = session.receiveResponse();
         // ...
     }

private:
    SomeLibrary::ClientSession session;
};
如何测试“send”方法(我真的发送了我想要的内容)?我不能模拟它。我可以写HTTPClient在构造函数中接收SomeLibrary :: ClientSession对象(在测试中我将传递模拟),但这是好设计吗?我认为会话等实现方式应该隐藏在我的类中。你有什么想法吗?
3个回答

9

我最近写了一个HTTP客户端库。

为了测试这个HTTP客户端库,我写了一个简单的测试代码,启动了一个std::thread监听在localhost上的某个随机端口。然后我告诉客户端使用hostport参数进行测试请求,在你的情况下,这些参数指向我的线程现在正在侦听的端口。这个线程的代码被编程为接受连接、读取HTTP请求、保存它,然后用预定义的HTTP响应作出回应。

这就是我如何测试我的客户端库,验证客户端发送的实际请求以及客户端处理预定义的HTTP响应的方式。后来,我开发了这个单元测试代码来发送各种HTTP错误和格式不正确的HTTP响应,以测试和验证客户端代码处理这些情况的方式。

此外,整个过程都由一个alarm()调用保护,因此如果某个地方陷入无限循环或其他问题,整个进程最终会自杀。

这就是你也可以用相同的方式测试你自己的代码。


0
你可以用socket模拟一个简单的HTTP服务器。 以下伪代码可能会有所帮助:
1) set up a string to send from the client, take its length in before hand
2) open a new thread with a socket in it
3) bind the socket into some port , listen and accept new connection
4) send the string you have setted with your http client
5) in the socket side, read until the length you saved has reached, save that string for comparison
6) send some pre-defined http response
7) close the socket 
7) close the thread
8) continue testing, you have the string which the server got, and the string which the client got, and the original strings which these was originated from

模拟分块传输和重定向很容易,但模拟SSL可能会相当困难。您可以使用openSSL或Boost SSL流提供的一些SSL流包装套接字。

另一个选择是在本地主机上使用已编写的HTTP服务器。使用Python或Node.js编写一个(仅用于测试)非常容易且适合该测试任务。在启动测试之前,激活服务器脚本(使用Node.js脚本很容易,只需system("node myServer.js")),测试完成后,关闭该服务器。


0

在构造函数中注入一个抽象的客户端会话实例。在单元测试中模拟它,在实际运行时传递一个真实的实例。

你说你不能在一句话中模拟,在下一句话中你说你可以——你是什么意思?如果你的意思是会话类不是“你自己的”,或者不能从中派生以便以这种方式进行模拟,那么你是否尝试将其包装在你自己的类中,以便它可以被模拟?

此外,你说“我认为会话等的实现方式应该隐藏在我的类中。”

你在这个假设中犯了一个谬误,即你的类,我猜你指的是HTTPClient,与此无关——应该隐藏其自身实现的是会话类,如果你将其作为实例传递给构造函数,它也可以这样做,从而总体上增加了无限的灵活性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接