gpt4 book ai didi

c++ - 如何注入(inject)模拟对象?

转载 作者:行者123 更新时间:2023-11-30 03:38:43 25 4
gpt4 key购买 nike

我正在尝试进行单元测试以测试 DoLogin 方法:

CLoginActivity::CLoginActivity()
{
m_pTask = new Task();
}

void CLoginActivity::DoLogin()
{
m_pTask.execute();
}

Task 是我需要模拟的另一个类。

class MockTask : public Task
{
public:
MOCK_METHOD0(Execute, void());

};

要注入(inject) MockTask 任务 对象,我必须更改我的构造:

CLoginActivity::CLoginActivity(Task& task)
{
m_pTask = task;
}

或者写一个集合函数:

CLoginActivity::SetTask(Task& task)
{
m_pTask = task;
}

是否有其他方法可以注入(inject)而不是这两种方法?我在我的单元测试项目中使用 gmock。

最佳答案

通过构造函数注入(inject)是最好的——保持这种设计。

但对于喜欢将简单事物复杂化的人来说,几乎没有其他方法。

1) 制作您的 CLoginActivity 类模板:

template <class TaskImpl>
class CLoginActivityTemplate
{
CLoginActivityTemplate() { m_pTask = new TaskImpl(); }
};

using CLoginActivity = CLoginActivityTemplate<Task>;

在你的测试中,测试这个实例:

using CLoginActivityTestable = CLoginActivityTemplate<TaskMock>;

然而,它并不总是那么容易 - 因为通常很难访问此模拟以在其上设置扩展。但是你可以定义 TestMockWrapper 类确保轻松访问模拟任务:

class TestMockWrapper : public TestMock
{
public:
static TestMock* lastCreated;
TestMockWrapper() { lastCreated = this; }
};
using CLoginActivityTestable = CLoginActivityTemplate<TaskMockWrapper>;

2) 将工厂对象注入(inject)到构造函数中:

CLoginActivity::CLoginActivity(ITaskFactory& taskFactory)
{
m_pTask = taskFactory.create();
}

您需要模拟此工厂类以确保模拟工厂创建模拟对象。也许它看起来没有希望 - 但这只是下一点的介绍。

3) 在其他文件中实现了特殊的工厂函数:

CLoginActivity.cpp

#include "TaskCreate.hpp"

CLoginActivity::CLoginActivity()
{
m_pTask = taskCreate();
}

TaskCreate.cpp

// your "real" function here
ITask* createTask() { return new Task(); }

具有这样的设计 - 仅使用项目中选定的文件为您的 CLoginActivity 创建 UT 测试 - 简单地说 - 在您的 UT 项目中将 TaskCreate.cpp 替换为 TaskcreateStub.cpp:

  1. CloginActivity.cpp
  2. TaskMock.cpp(如果存在)
  3. TaskCreateStub.cpp

TaskCreateStub.cpp 应该返回模拟任务——不是真正的任务。您还需要访问这个返回的模拟对象——这样您就可以对其设置期望。

TaskCreateStub.cpp

// your "real" function here
static TaskMock* taskMockForCreateStub = nullptr;
ITask* createTask() { return taskMockForCreateStub ; }
void setTaskMockForCreateTaskStub(TaskMock* taskMock) { taskMockForCreateStub = taskMock; }

我强烈建议您不要使用这种链接器级别的模拟。仅将它用于测试无法重新设计的遗留代码,这可能是使用模拟的唯一方法...

关于c++ - 如何注入(inject)模拟对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39364160/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com