当前位置: 首页 > news >正文

单例模式的mock类注入单元测试与友元类解决方案

问题背景:单例模式的测试挑战

在单元测试中,我们经常需要对单例模式进行测试,特别是当单例类依赖其他组件时。传统的单例模式通过静态方法获取实例,这使得依赖注入mock替换变得困难。

核心困境

我们需要在测试时:

  1. 注入Mock对象替换真实依赖

  2. 访问私有构造函数来创建带有mock依赖的实例

  3. 避免影响生产代码的单例行为

这是一个很常见的单例模式测试问题。你需要使用前向声明友元声明的正确组合来解决。以下是具体的解决方案:

解决方案步骤

1. 在单例类中前向声明测试类并声明为友元

在你的单例类头文件中(比如 singleton.h):

// singleton.h
#pragma once// 前向声明测试类
class SingletonTest;class Singleton {
public:static Singleton& GetInstance();// 公有方法void SomePublicMethod();private:// 私有构造函数Singleton();~Singleton();// 声明测试类为友元friend class SingletonTest;// 私有方法(测试需要访问的)void SomePrivateMethod();// 禁用拷贝和赋值Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;// 成员变量int some_data_;
};

2. 在测试文件中包含单例类头文件

在你的测试文件中(比如 singleton_test.cc):

// singleton_test.cc
#include "gtest/gtest.h"
#include "singleton.h"  // 必须包含单例类的完整定义class SingletonTest : public ::testing::Test {
protected:void SetUp() override {// 测试设置}void TearDown() override {// 测试清理}
};TEST_F(SingletonTest, TestPrivateMethod) {// 可以直接访问私有方法Singleton::GetInstance().SomePrivateMethod();// 或者通过其他方式测试// ...
}TEST_F(SingletonTest, TestConstructor) {// 如果需要测试构造函数逻辑,可以这样// 注意:单例模式通常不需要直接测试构造函数
}

更复杂的场景:如果测试类在不同的命名空间中

如果测试类在不同的命名空间,友元声明需要更精确:

单例类中:

// singleton.h
#pragma oncenamespace mynamespace {// 前向声明带命名空间的测试类namespace test {class SingletonTest;}class Singleton {public:static Singleton& GetInstance();private:Singleton();~Singleton();// 声明带命名空间的测试类为友元friend class test::SingletonTest;void SomePrivateMethod();};
}

测试类中:

// singleton_test.cc
#include "gtest/gtest.h"
#include "singleton.h"namespace mynamespace::test {class SingletonTest : public ::testing::Test {
protected:void SetUp() override {}void TearDown() override {}
};TEST_F(SingletonTest, TestPrivateAccess) {// 现在可以访问私有成员Singleton::GetInstance().SomePrivateMethod();
}} // namespace mynamespace::test

http://www.dtcms.com/a/357982.html

相关文章:

  • 云存储(参考自腾讯云计算工程师认证)
  • Twitter舆情裂变链:指纹云手机跨账号协同机制提升互动率200%
  • 使用电脑操作Android11手机,连接步骤
  • 【序列晋升】21 Spring Cloud Gateway 云原生网关演进之路
  • DVWA靶场通关笔记-CSRF(Impossible级别)
  • 【90页PPT】新能源汽车数字化转型SAP解决方案(附下载方式)
  • 汽车加气站操作工证考试的复习重点是什么?
  • 【自然语言处理与大模型】多机多卡分布式微调训练的有哪些方式
  • C++ constexpr:编译时计算的高效秘籍
  • 复现论文块体不锈钢上的光栅耦合表面等离子体共振
  • 10.2 工程学中的矩阵
  • hadoop安欣医院挂号看诊管理系统(代码+数据库+LW)
  • 使用 Ansible 和 Azure Pipelines 增强您的 DevOps
  • Midjourney绘画创作入门操作创作(广告创意与设计)
  • 腾讯云centos7.6的运维笔记——从yum的安装与更新源开始
  • C++ 之 【map和set的模拟实现】(只涉及map和set的插入、迭代器以及map的operator[]函数)
  • Altium Designer中电路板设计
  • 流式HTTP MCP服务器开发
  • Android中handler机制
  • 《RANKGUESS: Password Guessing Using Adversarial Ranking》——论文解读
  • 主从DNS和Web服务器搭建过程
  • Windows系统提示“找不到文件‘javaw‘”
  • 【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day16
  • Azure DevOps cherry pick
  • 基于IEC61499开放自动化PLC数据储存方案
  • Python 多线程日志错乱:logging.Handler 的并发问题
  • 42-Ansible-Inventory
  • AUTOSAR进阶图解==>AUTOSAR_TR_ClassicPlatformReleaseOverview
  • Spring Boot 日志操作全解析:从基础到实践
  • 加密软件哪个好用?加密软件-为数据共享提供安全保障