- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我阅读了很多与 Gtest 模拟相关的文档(例如 https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md,“Mocking Free Functions”),但找不到以下问题的解决方案:
source.cpp
H::H()
{
// some code1
if (to_be_mocked(id) != 0) { // some code2 }
// some code3
}
H& H::get_instance()
{
static H s;
return s;
}
unit_test.cpp
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "source.h"
TEST(Source, Constructor)
{
// What to write here to mock function "to_be_mocked"?
H& inst = H::get_instance();
}
int main(int argc, char** argv)
{
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
所以,我需要测试 H
的构造函数和模拟函数 to_be_mocked
中的整个代码,它在不同的翻译单元中定义。我怎样才能从 unit_test.cpp
做到这一点?
最佳答案
Dependency injection (DI) 来救援!
DI 是模拟的关键插入因素。具体来说,您可以使用 Strategy pattern 将依赖项注入(inject)此对象,以便您可以在测试时将其取出。
最简单的版本是将仿函数传递给您的构造函数,并在您当前调用 to_be_mocked()
的地方调用它。
在这种情况下,您的类看起来像这样:
class H
{
std::function<bool(int)> _to_be_mocked;
public:
H( std::function<bool(int)> fn )
: _to_be_mocked( std::move(fn) )
{
uses_mockable( 42 );
}
void uses_mockable( int id )
{
if( _to_be_mocked(id) ) { ... }
}
...
};
void MyTest()
{
auto my_mock_fn = ...;
auto h = H{ my_mock_fn };
// Set expectations to assert that my_mock_fn is used correctly
// and that the caller behaves properly in response to its return values
}
DI 不能很好地处理全局变量/单例变量,因为您不能(轻松地)在构建时注入(inject)依赖项,这是不鼓励它们的原因之一。
如果您不能将单例更改为常规实例或单独控制其初始构造,您可以在其中注入(inject)依赖项,那么您可以使用基于属性的注入(inject),在其中公开仿函数(或选择性地通过类似 Attorney-Client idiom 的东西) ) 然后在需要时进行设置。
在这种情况下,您的类将如下所示:
class H
{
std::function<bool(int)> _to_be_mocked;
static bool default_to_be_mocked( int ) { ... }
public:
H()
: _to_be_mocked( default_to_be_mocked ) // Use stand-alone function for default
{ /* can't use mock here */ }
// Could restrict accessibility here with Attorney-Client idiom or friendship
void set_to_be_mocked( std::function<bool(int)> fn )
{
_to_be_mocked = std::move( fn );
}
void uses_mockable( int id )
{
if( _to_be_mocked && _to_be_mocked( id ) ) { ... }
}
...
};
void MyTest()
{
auto my_mock_fn = ...;
auto& h = H::get_instance();
// ...
h.set_to_be_mocked( my_mock_fn );
// Set expectations to assert that my_mock_fn is used correctly
// and that the caller behaves properly in response to its return values
}
如果您需要在构造函数中调用 _to_be_mocked()
,则此方法无效,因此您必须使用前一种方法(首选)或选择选项 3。
如果您不能使用上述任何一种方法,则可以通过使用 Yet Another Global 来使用“穷人的 DI”(他们说,罪恶之源)。在不更改调用代码的情况下执行此操作的一种方法是将 to_be_mocked()
重命名为 to_be_mocked_impl()
并创建一个名为 to_be_mocked
:
bool to_be_mocked_impl( int id ) { ... } // used to be called to_be_mocked(int)
// Global instance that can be swapped out for testing.
// Defaults to the normal runtime function.
// Might use a raw function pointer instead of a std::function if you prefer.
auto to_be_mocked = std::function<bool(int)>{ to_be_mocked_impl };
class H
{
public:
H()
{
uses_mockable( 42 );
}
void uses_mockable( int id )
{
if( to_be_mocked(id) ) { ... }
}
...
};
void MyTest()
{
auto my_mock_fn = ...;
to_be_mocked = my_mock_fn; // Sets global ... blah!!
auto& h = H::get_instance();
// Set expectations to assert that my_mock_fn is used correctly
// and that the caller behaves properly in response to its return values
}
这使全局/单例的情况更加复杂,所以我不会推荐它,除非你出于不合理的原因不得不这样做。
PS,有一个 episode of CppCast on Dependency Injection 谈到了实验性的 [Boost.]DI library,可能在这里有用。
关于c++ - Gtest : mocking free function in a constructor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54650890/
这个问题在这里已经有了答案: How do free and malloc work in C? (8 个答案) 关闭 8 年前。 如果你使用malloc()为4个整数分配内存,它不应该返回第一个整
首先,介绍一下背景知识,这样您就不会认为我在尝试做一些疯狂的事情: 我正在尝试调试由其他人编写的 C 库中的崩溃。崩溃看起来像这样: TheProgram(44365,0x7fff75996310)
我正在 cstdlib malloc() 和 free() 函数之上创建自定义内存分配器(出于性能原因)。分配器位于一个简单的类中,该类存储一些内存缓冲区和其他参数。我想将释放内存的方法命名为 fre
我一直在解决这个练习,我不知道从哪里开始: 语言 B 是上下文无关的;语言 C 是 B 的子集:C 是否是上下文无关的?证明或反驳。 我试过使用闭包属性: C = B - ( (A* - C) ∩ B
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 8 年前。 Improve th
如果我想获得在 C 中进行 malloc 的指针的所有权,则 docs for the Python cffi package和 this answer假设使用 ffi.gc 和 lib.free 作
#include #include struct node { int value; struct node* next; }; typedef struct node node_
众所周知,Oracle 在 Java 11 中更改了 Java 许可证,要求 JDK 的商业用途需要付费许可证。然而,使用 OpenJDK 仍然是免费的。 我的 PC 上有一个 JDK 11 文件夹,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我是 C 的新手,在 Linux 中使用带有开关 gcc -g -std=c89 -Wall ... 的 gcc4.4.6 进行编程,我在许多函数深处遇到了这个错误我的程序名为 compute: **
在多线程编程中,我们可以找到两个或多个线程/任务之间的数据传输同步的不同术语。 什么时候我们可以说某个算法是: 1)Lock-Free 2)Wait-Free 3)Wait-Freedom 我明白无锁
我正在尝试使用我通过 malloc() 手动分配的数组来运行程序。我在程序末尾释放()这个数组,但我不断收到错误消息 *** glibc detector *** ./test: double fre
我将 libxml2 与 libxslt 一起用于 C++ 程序的 XML 处理。为了使用 XSL 转换 XML 文档,我使用了以下函数(删除了错误处理): xmlDocPtr transformXm
new/delete 关键字使用免费商店 malloc/free 关键字是使用堆 我看到某处写着new 使用malloc。怎么会这样?它们不在内存段中使用? 其次,我看到某处写道我们不能在new 之后
我有这个简单的代码,我想在 tutorialspoint.com 上运行 #include using namespace std; class Vehicle { string vehic
我需要创建一个函数来删除 c 中链表的前 n 个节点,并返回删除的节点数。如果列表小于 n,它应该变为空。 另外,我不能使用递归。 使用现在的代码,它可以工作,但我没有释放“已删除”节点的内存。如果我
我需要调试这段代码的帮助。我知道问题出在 malloc 和 free 中,但找不到确切的位置、原因和解决方法。请不要回答:“使用 gdb”,仅此而已。我会使用 gdb 来调试它,但我仍然不太了解它并且
这个问题在这里已经有了答案: Unable to free const pointers in C (12 个答案) 关闭 8 年前。 将 C++11 代码连接到某些 C 回调,我必须传递 cons
这是出于好奇,我试图找到我对之前问题的疑问的答案,但他们似乎没有答案。所以在这里问,我只是写了一个代码,我试图将内存分配给一个 int 指针(以填充一个数组)并将 int 值扫描到它。完成数组后,我想
我有两个免费的单子(monad),用于不同上下文中的不同操作。但是,如果特定操作位于上下文中,则一个(主要)DSL 需要包含另一个(action)DSL: import Control.Monad.F
我是一名优秀的程序员,十分优秀!