我想计算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 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);
}
}
现在我的问题。如何使用" dummy"覆盖我的存根中的Method()。计算通话次数的变量?我有虚拟到位,它按预期调用,但我不能使它增加一个计数器,因为它被声明为const。我想在我的AStub中添加一个计数器,并让AStub :: Method()增加计数器作为虚拟实现的一部分,但考虑到它的声明方式,这看起来很棘手。
我不能使用像谷歌模拟或类似的任何模拟框架,但必须有一些共同的解决方案来解决这个问题。人们通常会如何处理这个小障碍?
由于
答案 0 :(得分:2)
如果您正在使用继承,则可能需要将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;
}
最后,执行Method
,增加调用次数,然后调用原始函数:
void AStub::Method() const
{
numCalls++;
A::Method();
}
答案 1 :(得分:2)
如果问题是如何在const方法中修改成员变量,那么答案很简单:使用mutable
关键字。
这样的事情应该有效:
class AStub : public A
{
public:
const void Method() const{ ++n; }
mutable int n;
};
答案 2 :(得分:1)
您可以使用模拟框架为您完成工作。无需实现自己的模拟类(AStub)。 以下是Fake-It的使用方法。一个简单的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);