当前位置: 首页 > 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.xdnf.cn/news/1399483.html

相关文章:

  • Android15适配16kb
  • ros2 foxy没有话题问题解决
  • Axios 实例配置指南
  • Keil5 MDK_541官网最新版下载、安装
  • 从 0 到 1 构建零丢失 RabbitMQ 数据同步堡垒:第三方接口数据零丢失的终极方案
  • comfUI背后的技术——VAE
  • 线性代数理论——状态空间
  • 聊一聊耳机串扰-Crosstalk
  • Vue常用指令和生命周期
  • 118、【OS】【Nuttx】【周边】效果呈现方案解析:作用域?
  • 生成一份关于电脑电池使用情况、健康状况和寿命估算的详细 HTML 报告
  • 软考中级习题与解答——第一章_数据结构与算法基础(2)
  • 【Redisson 加锁源码解析】
  • VuePress添加自定义组件
  • 【MySQL数据库】索引 - 结构 学习记录
  • 加速智能经济发展:如何助力“人工智能+”战略在实时视频领域的落地
  • Swift 解法详解:LeetCode 367《有效的完全平方数》
  • Kafka入门
  • 开源 C++ QT Widget 开发(八)网络--Http文件下载
  • 《微服务架构从故障频发到自愈可控的实战突围方案》
  • CSDN博客语法(不常用但有用)
  • 谷歌 “Nano Banana“ 深度解析:AI 图像的未来是精准编辑,而非从零生成
  • ⚡ Linux find 命令参数详解
  • MySQL基础理解入门
  • 嵌入式硬件电路分析---AD采集电路
  • Spring Boot 自动配置原理深度解析:从启动流程到监听机制
  • 【Java EE进阶 --- SpringBoot】Spring Web MVC(Spring MVC)(二)
  • 设计模式之代理模式!
  • 深度学习基础:前馈网络、反向传播与梯度问题
  • 基于IEC61499开放自动化PLC数据储存方案