我正在尝试为我正在处理的项目编写单元测试(用Qt编写,用Qt编写),但由于我的代码在很大程度上取决于网络响应,因此我遇到了困难。我的项目包含一个具有三个重要功能的主类。工作流程看起来像这样:
// 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
}
为了清晰起见,我遗漏了大部分细节,但上面的代码很好地说明了课程的组织方式。应该调用类中的一个函数来启动进程,并在网络请求完成时调用其他函数,以便可以处理这些请求的结果。
我想单独测试每个函数,以便我可以抛出许多不同的响应和不同的错误情况,以确保我的代码在每种情况下都能正确反应。问题是我不需要或希望我的功能在这些测试期间实际发出任何互联网请求。我在网上搜索过,但没有找到任何真正好的解决方案。以下是我找到的选项:
链接器技巧
get
函数实际上不会发出任何网络请求。然后在编译期间,我将我的代码链接到这个模拟类,而不是Qt附带的那个。预处理程序指令
这个想法涉及创建一个模拟对象,比方说QNetworkAccessManager_Mock
,并在我的一个测试文件中定义一个宏,例如:#define TESTCASE
。然后在我尝试测试的代码中,我将QNetworkAccessManager manager;
的实例替换为:
#ifdef TESTCASE
QNetworkAccessManager_Mock manager;
#else
QNetworkAccessManager manager;
#endif
此选项在小型项目中相对容易实现,但在大型项目中可能会变得难以驾驭,因为您的代码必须充满#ifdef
个部分。我不喜欢这个选项涉及的原始代码的修改级别
使用脚本编辑我的源文件
QNetworkAccessManager
的每个实例。修改每个请求的目标网址
localhost:9000
。在这种情况下,每个网络请求都会以可预测的方式失败,但是为了让它发挥作用似乎太过分了。只是不要写测试。
如果我是编写依赖类的依赖项,那么存在大量用于模拟依赖项的示例。但是,似乎没有任何干净简单的解决方案来模拟其他库中存在的依赖类。上面概述的解决方案是我唯一的选择,还是我忽略了什么?你会推荐什么作为我的最佳选择?
答案 0 :(得分:0)
我认为这是使用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类。