- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用 googletest 学习单元测试,但不确定如何覆盖函数。简而言之,我需要了解在母函数 M 中定义的 lambda 函数(假设为 L)。M 调用函数 C(在另一个文件中定义),该函数将 lambda 函数 L(回调)作为参数。我正在为 M 编写单元测试,需要调用 M,模拟外部函数 M,同时确保模拟 C 并正确覆盖 L。
简而言之,object->M 有 L,M 调用 C(L)。
谷歌测试有办法做到这一点吗?
我已经尝试过的一般形状:
/* source code */
/* header */
struct Object
{/*struct methods*/
//M declaration
int M();
};
/* cpp file */
int M()
{
/* some operations */
auto L = [](int number){/* operations, returns 0; */};
int store; //storing the result of C
store = C(L);
}
/* other file */
int C(int* L(int))
{
/* some operations */
L(1);
return some_int;
}
单元测试文件代码:
#include <gmock/gmock.h>
#include <gtest.h>
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::DoAll;
using ::testing::SetArgReferee;
using ::testing::SetArgPointee;
using ::testing::SetArrayArgument;
using ::testing::_;
/* mock class*/
class MockedFunctions
{
public:
/* going to put 5 ints for the sake of the example */
MOCK_METHOD1(C, int(int));
};
class TestObject : public ::testing::Test
{
public:
TestObject(){}
~TestObject(){}
protected:
Object *objectInstance;
virtual void SetUp()
{ objectInstance = new Object;}
virtual void TearDown()
{ delete objectInstance;}
};
/* test for function */
TEST_F(TestObject, test_M)
{
MockedFunctions test_C;
EXPECT_CALL(test_C, C(_))
.Times(1)
/* don't care about passed number to L */
.WillOnce(DoALL (SetArgPointee<0>(L(3)), Return(0));
/* coud put EXPECT_EQ as well */
objectInstance->M();
}
这在 .WillOnce 处给我一个错误,指出 L 未在此范围内声明。
注意,我不关心L的内容,只要覆盖就可以了。到目前为止,我发现关于这个主题的建议是模拟我的 lambda 函数 L,我不想在这里做,因为我需要覆盖它的代码作为函数 M 的一部分。
虽然我不需要,但在这种情况下,严格使用 GTest 风格(因为我的导师不知道如何继续这个 L 函数覆盖)并且可以使用 C 的 stub 来强制使用 L(我现在已经实现了这个版本,以便能够与其余代码一起编译),是否仍然可以严格使用 googletest 样式来获得此覆盖率?
谢谢!
最佳答案
最终找到解决方案并发布以供引用;
我的解决方案是找到一种方法将我感兴趣的回调方法存储在容器内,为此创建辅助方法并从该 vector 中获取一些输出。
MockedFunctions 类型的静态指针用于提供一个对象,以便在我们所需的数据被提取后“恢复”正常的模拟控制行为。
//inside my header file.
#include <gmock/gmock.h>
#include <vector>
class MockedFunctions {
public:
//lets say function L has params (int, void*)
typedef int (myCb) (int arg_from_cb_L, void* objptr_from_cb_L));
MockedFunctions(){}
virtual ~MockedFunctions(){}
//giving C more arguments than just the callback L
MOCK_METHOD2(C, int(int arg1, int(*L)(int, void*));
private:
//note due to namespace limitations, I'm including the std prefix
std::vector<myCb> callback_storage;
void *cb_obj_copy;
public:
/* Multiple public blocks just for readability purposes.
* Note the internal usage of vector methods.
*/
void cb_clear(){
if(callback_storage.empty())
{
callback_storage.clear();
}
}
void cb_add(myCb callback){
callback_storage.push_back(callback);
}
myCb* cb_result_at(int i){
return callback_storage.at(i);
}
//to store one of the params from the passed callback
void cb_copy_obj(void* obj){
cb_obj_cb = obj;
}
void cb_get_obj_copy(){
return cb_obj_copy;
}
};
class TestMethods : public ::testing::Test
{
public:
static std::unique_ptr<MockedMethods> testMockedMethods;
TestMethods(){
/* as we call other methods from MockedMethods apart from C,
* it would trigger warnings. Using NiceMock hides them for
* cleaner output.
*/
testMockedMethods.reset(new ::testing::NiceMock<MockedMethods>());
}
~TestMethods() override{
testMockedMethods.reset();
}
virtual void SetUp() override {}
virtual void TearDown() override {}
};
现在,在我的 cpp 文件中,我定义了 C 并实例化了指针。
std::unique_ptr<MockedMethods> TestObject::testMockedMethods(new MockedMethods() );
int C ( int arg1, int(*L)(int arg1_cb, void* arg2_cb)){
TestMethods::testMockedMethods->cb_add(L);
TestMethods::testMockedMethods->cb_copy_obj(arg2_cb);
/* to avoid complications, took L's return type of int and put a 0
* directly, we don't care at this point since we will overload the
* method afterwards.
*/
return TestMethods::testMockedMethods->C(arg1, 0);
}
至于实际测试,放在你认为合适的地方:
class TestCaseClass : public TestMethods
{
public:
TestCaseClass(){}
~TestCaseClass(){}
protected:
//Here, object is the struct name mentioned previously in the question.
Object *instance;
// ...
virtual void SetUp()
{
instance = new Object();
// ...
}
virtual void TearDown()
{
delete instance;
}
};
TEST_F(TestCaseClass, test_M)
{
// testing method M from struct Object
/* Run tests normally on C, results will be stored. By our definition, a different object
* will be the one calling C, so pay attention to it.
*/
EXPECT_CALL(*testMockedMethods, C(_, _))
.Times(1)
.WillOnce(Return(1))
// I noticed at this point M above did not return anything, suppose it returns store
EXPECT_EQ(instance->M(), 1);
// Now to get coverage or data from our callback. First, get the method in cb_obj
MockedMethods::myObj* cb_method = testMockedMethods->cb_result_at(0);
// Now get one of its arguments, like that void*. Note we're using our get-ers
void* mock_object = testMockedMethods->cb_get_obj_copy();
/* And finally, call our method, finally getting coverage. You can pass
* various parameters for branching.
*/
cb_method(0, mock_object);
// Don't forget we clear the vector of contents in case we re-use it in another test.
testMockedMethods->cb_clear();
}
虽然不是最直接的解决方案,但它被证明是有效的,我尝试包含一些在创建测试时可能遇到的用例。
编码愉快!
关于c++ - 如何模拟采用已定义的 lambda 函数并覆盖 lambda 函数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55395837/
考虑以下代码: template struct list { template list(Args...) { static_assert(sizeof..
考虑以下代码: template struct list { template list(Args...) { static_assert(sizeof..
最近才开始学习"new"OpenGL(可编程而不是固定功能,我从 Nehe 教程中学到的),我想知道自从 OpenGL 4 发布以来学习 OpenGL 3 是否真的有用。 我问的原因是因为我想知道能够
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我想了解如何操作特征向量/矩阵。我想实现最小二乘高斯牛顿算法(因此我学习使用 Eigen 库)。我有一个 1x6 的参数 vector ,每次迭代都需要更新它们。现在,我只想弄清楚函数如何将 vect
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 5 年前。 Improv
我发现编写适用于Enums的静态方法非常困难。这是一个非常人为的示例,但假设您想要编写一个方法,该方法采用 Enum 常量并返回下一个声明的常量。我发现(大约一个小时后)你可以按如下方式进行。它可以工
我正在尝试编写一个函数,在某些条件下,将指向结构的指针更改为指向不同的结构。 我的限制是我想保留初始函数签名,该签名将指向指针(而不是特定结构类型)的通用指针作为参数。 这行不通: [nav] In
我正在尝试将 Keras 示例改编为 VAE https://blog.keras.io/building-autoencoders-in-keras.html 我修改了代码,使用有噪声的 mnist
自 JPA 2.0 以来,关系上有 orphanRemoval 属性,它极大地简化了父子关系的更新,并且与级联删除一起允许删除树的整个分支并轻松删除它。 但是,也有一些情况可能被标记为“收养”,即您将
我正在尝试编写一个类,它能够在以后及时调用不带参数的 lambda。我期待 C++17 类模板参数推导以避免需要工厂函数。但是,尝试在不指定类型的情况下实例化对象会失败。我可以很好地使用工厂功能,但我
我怎样才能避免并非所有控制路径都在此处返回容器的事实: enum Type {Int, String}; Container containerFactory(Type
我开始学习 C++ 和 STL。 我有一个问题: 写一个函数模板palindrome,接受一个 vector 参数并返回true或false来检查 vector 是否是回文(12321是回文,1234
我一直在尝试获取一个条目值(代码中的 S1)以将其自身设置为一个值(_attributes 字典中的 STR),但我就是无法让它工作。我想让它成为一个最终的顶层循环,但我在这方面一步一步来,因为我是一
我想做同样的事情 How do I get the number of days between two dates in JavaScript? 但我想对此日期格式执行相同操作:2000-12-31
我想编写一个带有构造函数的 C++ 类,该构造函数将 auto_ptr 作为其参数,以便我可以将类实例从 auto_ptr 初始化为另一个实例: #include class A { public:
我需要一种方法,我可以在其中获取二维数组中的输入并以最快的方式之一对其进行逐行排序。我尝试使用 Insertion Sort 同时获取 Input 和 Sort it。我使用的第二件事是我单独为一行取
好的,我已经阅读了一些关于 IDisposable 最佳实践的文章,我想我基本上明白了(终于)。 我的问题与从 IDisposable 基类继承有关。我看到的所有示例都在子类中一遍又一遍地编写相同的代
定义类时,以下是否有效? T(const T&&) = default; 我正在阅读移动构造函数 here并且它解释了如何仍然可以隐式声明默认值: A class can have multiple
我想使用 LoadLibrary 开发一个插件系统。 我的问题是:我希望我的函数采用 const char* 而 LoadLibrary 采用 LPCTSTR。 我有一个聪明的想法来做(LPCSTR)
我是一名优秀的程序员,十分优秀!