Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何存根/模拟常量函数_C++_Unit Testing_Mocking_Stub - Fatal编程技术网

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

我想计算类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);
  }
}
现在来谈谈我的问题。如何使用计算调用数的“伪”变量重写存根中的方法()?我将虚拟对象放在适当的位置,并按预期调用它,但我无法使其递增为计数器,因为它被声明为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));

谢谢,您也指出了我发布的简化实现中的一些问题,但关键是可变的。我以前从未见过这种情况。现在效果很好!谢谢,您还指出了我发布的简化实现中的一些问题,但关键是可变的。我以前从未见过这种情况。现在效果很好!