C++中用gMock监控Qt QProcess调用:简化Wrapper实现的方案
解决QProcess Wrapper重复实现的几种方案
在测试Qt的QProcess时,避免手动重复编写Wrapper的转发代码,有以下几种实用方案:
方案1:CRTP(奇异递归模板模式)自动生成转发代码
利用编译期模板继承,将通用的转发逻辑封装在基类中,生产环境的Wrapper只需继承该模板并持有QProcess实例即可,无需手动实现每个接口方法。
代码示例
首先定义统一的IQProcess接口:
class IQProcess { public: virtual ~IQProcess() = default; virtual void start(const QString& program, const QStringList& arguments) = 0; virtual void kill() = 0; virtual bool waitForFinished(int msecs = 30000) = 0; virtual QString readAllStandardOutput() = 0; // 根据需求添加其他QProcess方法 };
然后编写CRTP模板基类,实现通用转发逻辑:
template <typename Derived> class QProcessWrapperBase : public IQProcess { protected: // 获取子类实例,用于访问QProcess成员 Derived* derived() { return static_cast<Derived*>(this); } const Derived* derived() const { return static_cast<const Derived*>(this); } public: void start(const QString& program, const QStringList& arguments) override { derived()->process.start(program, arguments); } void kill() override { derived()->process.kill(); } bool waitForFinished(int msecs = 30000) override { return derived()->process.waitForFinished(msecs); } QString readAllStandardOutput() override { return derived()->process.readAllStandardOutput(); } // 所有接口方法的转发逻辑都在这里统一实现 };
生产环境的Wrapper只需简单继承模板类并持有QProcess:
class QProcessWrapper : public QProcessWrapperBase<QProcessWrapper> { public: QProcess process; // 直接持有QProcess实例 };
测试用的Mock类正常实现IQProcess接口即可:
class QProcessMock : public IQProcess { public: MOCK_METHOD(void, start, (const QString& program, const QStringList& arguments), (override)); MOCK_METHOD(void, kill, (), (override)); MOCK_METHOD(bool, waitForFinished, (int msecs), (override)); MOCK_METHOD(QString, readAllStandardOutput, (), (override)); };
优点:编译期类型安全,无运行时开销,转发逻辑集中维护,修改接口只需改动基类一次。
方案2:宏定义生成转发代码
通过宏自动生成Wrapper的方法实现,减少手动重复书写的工作量。
代码示例
class IQProcess { public: virtual ~IQProcess() = default; virtual void start(const QString& program, const QStringList& arguments) = 0; virtual void kill() = 0; virtual bool waitForFinished(int msecs = 30000) = 0; virtual QString readAllStandardOutput() = 0; }; // 定义宏,自动生成转发方法 #define WRAP_QPROCESS_METHOD(method_name, signature, call_expr) \ void method_name signature override { \ process.call_expr; \ } class QProcessWrapper : public IQProcess { private: QProcess process; public: WRAP_QPROCESS_METHOD(start, (const QString& program, const QStringList& arguments), start(program, arguments)) WRAP_QPROCESS_METHOD(kill, (), kill()) WRAP_QPROCESS_METHOD(waitForFinished, (int msecs), waitForFinished(msecs)) WRAP_QPROCESS_METHOD(readAllStandardOutput, (), readAllStandardOutput()) };
优点:写法简洁,无需模板语法,适合快速实现;缺点:宏的调试体验较差,若方法签名复杂可能需要调整宏的写法。
方案3:继承QProcess实现接口(不推荐)
直接让Wrapper同时继承IQProcess和QProcess,然后在接口方法中调用QProcess的对应方法。这种方式省去了持有QProcess实例的步骤,但仍需手动实现每个接口方法,本质上和你原来的做法区别不大,仅减少了成员变量定义,无法避免重复代码,因此不推荐。
内容的提问来源于stack exchange,提问作者ataraxis
相关产品推荐
相关产品推荐

