C++ 如何存根/模拟常量函数
我想计算类a中的某个函数被类B中的另一个函数调用的次数。这是在类B的类测试中完成的,在这个测试中,类a是存根的 <>这里,我试图用C++代码解释相关的类:C++ 如何存根/模拟常量函数,c++,unit-testing,mocking,stub,C++,Unit Testing,Mocking,Stub,我想计算类a中的某个函数被类B中的另一个函数调用的次数。这是在类B的类测试中完成的,在这个测试中,类a是存根的 这里,我试图用C++代码解释相关的类: class X { const void Method() const = 0; } class A : public X { const void Method() const; } class AStub : public A { const void Method() const; U32 getNumberOfCall
class X
{
const void Method() const = 0;
}
class A : public X
{
const void Method() const;
}
class AStub : public A
{
const void Method() const;
U32 getNumberOfCallsToMethod();
}
class B
{
void runAlgorithm();
A* getA(); // returns pointer to the A instance used by B
}
class BTest
{
void test_runAlgorithm()
{
B b;
// b is setup to use a stub of A rather than A..
// ...
U32 before = ((AStub*)b.getA())->getNumberOfCallsToMethod();
b.runAlgorithm();
U32 after = ((AStub*)b.getA())->getNumberOfCallsToMethod();
// Verify that Method() has been run exactly once
ASSERT_EQUAL("Unexpected number of calls to Method()",
before + 1, after);
}
}
现在来谈谈我的问题。如何使用计算调用数的“伪”变量重写存根中的方法()?我将虚拟对象放在适当的位置,并按预期调用它,但我无法使其递增为计数器,因为它被声明为const。我想在AStub中添加一个计数器,并让AStub::Method()增加计数器,作为虚拟实现的一部分,但考虑到它的声明方式,这似乎很棘手
我不能使用任何模仿框架,比如GoogleMock或类似的,但必须有一些通用的解决方案来解决这个问题。一个人通常如何克服这个小障碍
谢谢如果您使用的是继承,您可能需要将
方法
声明为虚拟:
class X
{
virtual void Method() const = 0;
};
(还删除了const void
,因为它没有意义-const
在成员函数足以使其成为const函数之后)
然后使用mutable
关键字告诉编译器“我希望这个特定的成员变量即使在const
调用中也不能更改”-调用这个变量numCalls
,将默认构造函数添加到零numCalls
class AStub : public A
{
public:
AStub() : numCalls(0) {}
void Method() const;
U32 getNumberOfCallsToMethod();
private:
mutable U32 numCalls;
}
最后,执行方法
,该方法增加调用次数,然后调用原始函数:
void AStub::Method() const
{
numCalls++;
A::Method();
}
如果您使用的是继承,则可能需要将
方法
声明为虚拟:
class X
{
virtual void Method() const = 0;
};
(还删除了const void
,因为它没有意义-const
在成员函数足以使其成为const函数之后)
然后使用mutable
关键字告诉编译器“我希望这个特定的成员变量即使在const
调用中也不能更改”-调用这个变量numCalls
,将默认构造函数添加到零numCalls
class AStub : public A
{
public:
AStub() : numCalls(0) {}
void Method() const;
U32 getNumberOfCallsToMethod();
private:
mutable U32 numCalls;
}
最后,执行方法
,该方法增加调用次数,然后调用原始函数:
void AStub::Method() const
{
numCalls++;
A::Method();
}
如果问题是如何在const方法中修改成员变量,那么答案很简单:使用
mutable
关键字
像这样的方法应该会奏效:
class AStub : public A
{
public:
const void Method() const{ ++n; }
mutable int n;
};
如果问题是如何在const方法中修改成员变量,那么答案很简单:使用
mutable
关键字
像这样的方法应该会奏效:
class AStub : public A
{
public:
const void Method() const{ ++n; }
mutable int n;
};
您可以使用模拟框架来完成这项工作。无需实现自己的模拟类(AStub)。 以下是您如何使用的。一个简单的C++模拟框架:
class X
{
public:
virtual const void foo() const = 0;
};
class A : public X
{
public:
virtual const void foo() const override {}
};
class B
{
A& _a;
public:
B(A& a):_a(a){}
void runAlgorithm() { _a.foo(); }
A& getA() { return _a; }
};
A a;
Mock<A> mock(a);
Spy(Method(mock,foo)); // Spy A::foo on the mock object.
// Instantiate B (class under test) and inject the mock instance.
B b(mock.get());
// Run the tested method.
b.runAlgorithm();
// Verify the A::foo of the injected object was invoked exactly once.
Verify(Method(mock,foo)).Exactly(Once);
X类
{
公众:
虚拟常量void foo()常量=0;
};
A类:公共X
{
公众:
虚常量void foo()常量重写{}
};
B类
{
A和u A;
公众:
B(A&A):_A(A){}
void runAlgorithm(){u a.foo();}
A&getA(){return\u A;}
};
A A;
模拟(a);
间谍(方法(模拟,foo));//在模拟对象上监视A::foo。
//实例化B(测试中的类)并注入模拟实例。
B(mock.get());
//运行测试过的方法。
b、 运行算法();
//验证注入对象的A::foo只调用了一次。
准确地(一次)验证(方法(模拟、foo));
您可以使用模拟框架来完成这项工作。无需实现自己的模拟类(AStub)。
以下是您如何使用的。一个简单的C++模拟框架:
class X
{
public:
virtual const void foo() const = 0;
};
class A : public X
{
public:
virtual const void foo() const override {}
};
class B
{
A& _a;
public:
B(A& a):_a(a){}
void runAlgorithm() { _a.foo(); }
A& getA() { return _a; }
};
A a;
Mock<A> mock(a);
Spy(Method(mock,foo)); // Spy A::foo on the mock object.
// Instantiate B (class under test) and inject the mock instance.
B b(mock.get());
// Run the tested method.
b.runAlgorithm();
// Verify the A::foo of the injected object was invoked exactly once.
Verify(Method(mock,foo)).Exactly(Once);
X类
{
公众:
虚拟常量void foo()常量=0;
};
A类:公共X
{
公众:
虚常量void foo()常量重写{}
};
B类
{
A和u A;
公众:
B(A&A):_A(A){}
void runAlgorithm(){u a.foo();}
A&getA(){return\u A;}
};
A A;
模拟(a);
间谍(方法(模拟,foo));//在模拟对象上监视A::foo。
//实例化B(测试中的类)并注入模拟实例。
B(mock.get());
//运行测试过的方法。
b、 运行算法();
//验证注入对象的A::foo只调用了一次。
准确地(一次)验证(方法(模拟、foo));
谢谢,您也指出了我发布的简化实现中的一些问题,但关键是可变的。我以前从未见过这种情况。现在效果很好!谢谢,您还指出了我发布的简化实现中的一些问题,但关键是可变的。我以前从未见过这种情况。现在效果很好!