我正在尝试为我正在研究的项目编写单元测试(使用Qt用C ++编写),但是由于我的代码主要取决于网络响应,因此我遇到了困难。我的项目包含一个具有三个重要功能的主类。工作流程如下所示:
// myclass.h
#include <QNetworkAccessManager>
class MyClass
{
void function1();
void function2();
void function3();
QNetworkAccessManager manager; // this is the object used to make network requests
}
// myclass.cpp
#include "myclass.h"
MyClass::function1()
{
// this function should be called to start the chain of events
// set up the first request
manager.get("www.myserver.com");
}
MyClass::function2()
{
// this function is called with the response of the request made in function1
// process the results of the first request
// set up the second request
manager.get("www.yourserver.com");
}
MyClass::function3()
{
// this function is called with the results of the second request
// process the results of the second request
}
为了清楚起见,我省略了大部分细节,但是上面的代码很好地说明了类的组织方式。类中应调用一个函数来启动该过程,而在网络请求完成时调用另一个函数,以便可以处理这些请求的结果。
我想分别测试每个函数,以便可以抛出很多不同的响应和不同的错误情况,以确保我的代码在每种情况下都能正确响应。问题是我不需要或不希望我的功能在这些测试期间实际发出任何互联网请求。我在网上搜索过,但没有找到任何真正好的解决方案。这是我找到的选项:
链接器技巧
这里的想法是创建一个也称为QNetworkAccessReply的模拟类,它具有一个虚拟的
get
函数,该函数实际上不会发出任何网络请求。然后在编译时,我将代码链接到该模拟类,而不是Qt附带的那个类。就不需要修改我的课程而言,这个主意似乎是最干净的,但是我一直无法弄清楚如何在实践中实现这一点。
预处理程序指令
这个想法涉及创建一个模拟对象(假设为
QNetworkAccessManager_Mock
),并在我的一个测试文件中定义一个宏,例如:#define TESTCASE
。然后在我尝试测试的代码中,我将QNetworkAccessManager manager;
的实例替换为:#ifdef TESTCASE
QNetworkAccessManager_Mock manager;
#else
QNetworkAccessManager manager;
#endif
此选项在小型项目中相对容易实现,但是在大型项目中可能会变得难以控制,在大型项目中,您的代码必须充满
#ifdef
部分。我不喜欢此选项涉及的原始代码修改级别使用脚本编辑我的源文件
我可以创建一个贯穿我的源文件的简单脚本,用模拟类代替
QNetworkAccessManager
的每个实例。此选项使我可以保持源代码不变,并且在编译时不必弄乱正确链接,但是似乎不需要很多额外的开销。
修改每个请求的目标网址
我可以为我不知道的本地服务器选择一个URL,例如
localhost:9000
。在这种情况下,每个网络请求都将以可预见的方式失败,但是为了使它正常工作似乎太多了。或者,我的单元测试可以启动本地服务器,从中我可以返回一些固定的响应。在我看来,仅检查每个单独的函数如何响应就需要太多开销,而且仍然无法让我检查我的班级如何应对必须处理网络故障的错误。
无论哪种情况,我都仍需要一种使用预处理器指令来修改url的方法,使我重新回到#2和#3的问题。
只是不要编写测试。
此选项无法实现全部目的
如果我是编写依赖类的人,那么有很多示例可以用来模拟依赖。但是,对于模拟其他库中存在的依赖类而言,似乎没有任何简单明了的解决方案。我上面概述的解决方案确实是我唯一的选择,还是我忽略了某些东西?您会推荐什么作为我的最佳选择?
最佳答案
我认为最好的解决方案只是在使用c ++类聚合。您可以创建如下的Helper类:
class Helper
{
void function1();
void function2();
void function3();
}
并在MyClass中聚合此类。 MyClass.h:
#include <QNetworkAccessManager>
#include "Helper.h"
class MyClass
{
void function1();
void function2();
void function3();
Helper helper;
QNetworkAccessManager manager; // this is the object used to make network requests
}
MyClass.cpp:
#include "myclass.h"
MyClass::function1()
{
helper.function1();
manager.get("www.myserver.com");
}
MyClass::function2()
{
helper.function2();
manager.get("www.yourserver.com");
}
MyClass::function3()
{
helper.function3();
}
在这种情况下,您需要测试Helper类。
关于c++ - Qt中的单元测试高度依赖(网络依赖)功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31038088/