C++11 c+中的模拟静态方法+;

C++11 c+中的模拟静态方法+;,c++11,googletest,googlemock,C++11,Googletest,Googlemock,我刚开始使用googleTest进行单元测试。 在这种情况下,一个类的静态方法在另一个类中调用 class A { public: static bool retriveJsonData(std::string name, Json::Value& responseJsonData); } 在另一个类中,我使用的是类A RetrieveJsonData方法 class B { public: bool Method1 (std::string name) {

我刚开始使用googleTest进行单元测试。 在这种情况下,一个类的静态方法在另一个类中调用

class A {
  public:
   static bool retriveJsonData(std::string name, Json::Value& responseJsonData);
}
在另一个类中,我使用的是类A RetrieveJsonData方法

class B {
   public:
     bool Method1 (std::string name) {
        Json::Value sampleJsonData;
        return A::retriveJsonData(name, sampleJsonData);
 }
对A类的嘲弄

class MockA : public A {
  public:
    MOCK_MEHTOD2(retriveJsonData, bool(std::string, Json::Value));
}

现在我必须在使用EXPECT\u调用测试类B的Method2时模拟RetrieveJSONDATA


请帮助我解决如何测试这种情况?

在类B中使用A作为模板参数(请参阅)

模板
B类{
公众:
布尔方法1(标准::字符串名称){
Json::Value sampleJsonData;
return T::retrievejsondata(名称,sampleJsonData);
}
}
然后在测试中使用:

B<MockA> b;
B;
在生产代码中:

B<A> b;
B;

使用A作为B类中的模板参数(请参阅)

模板
B类{
公众:
布尔方法1(标准::字符串名称){
Json::Value sampleJsonData;
return T::retrievejsondata(名称,sampleJsonData);
}
}
然后在测试中使用:

B<MockA> b;
B;
在生产代码中:

B<A> b;
B;

Google Mock的模拟类型提供了检查非静态成员函数的预期调用的方法,其中虚拟函数多态性或模板可以用作“接缝”,在模拟函数中交换真实函数。如果你能设计或重构所有东西来使用其中一种技术,那就太好了。但有时在凌乱的遗留代码或使用外部库的代码中以这种方式工作会很麻烦

在这种情况下,另一个选项是定义一个依赖函数,它不是一个非静态成员函数(所以是自由函数或静态成员),以重定向到某个单例模拟对象。假设我们有一些要进行单元测试的翻译单元(B.cpp),它调用一些未在该翻译单元中定义的非成员或静态成员函数(
A::retrieveJsonData

通常,对于单元测试B.cpp,我们会注意到它所需的链接器符号,并为它们提供假定义,以将它们剔除,只是为了让对象文件B.o链接到单元测试程序:

// Fake definition:
bool A::retrieveJsonData(std::string, Json::Value&)
{ return false; }
在这种情况下,我们不希望有虚假的定义;稍后我们将定义它以重定向到模拟对象

从专门针对有问题的函数调用的模拟类开始。如果有其他非静态成员函数以普通方式进行测试,则该类与这些类不同。(如果不止一个函数需要这样做,这些模拟类可以针对每个函数、每个类和/或一个用于自由函数、每个库、一个用于所有函数;但是您需要设置它。)


GoogleMock的Mock类型提供了检查非静态成员函数的预期调用的方法,其中虚拟函数多态性或模板可以用作“接缝”,以便在模拟函数中交换真实函数。如果你能设计或重构所有东西来使用其中一种技术,那就太好了。但有时在凌乱的遗留代码或使用外部库的代码中以这种方式工作会很麻烦

在这种情况下,另一个选项是定义一个依赖函数,它不是一个非静态成员函数(所以是自由函数或静态成员),以重定向到某个单例模拟对象。假设我们有一些要进行单元测试的翻译单元(B.cpp),它调用一些未在该翻译单元中定义的非成员或静态成员函数(
A::retrieveJsonData

通常,对于单元测试B.cpp,我们会注意到它所需的链接器符号,并为它们提供假定义,以将它们剔除,只是为了让对象文件B.o链接到单元测试程序:

// Fake definition:
bool A::retrieveJsonData(std::string, Json::Value&)
{ return false; }
在这种情况下,我们不希望有虚假的定义;稍后我们将定义它以重定向到模拟对象

从专门针对有问题的函数调用的模拟类开始。如果有其他非静态成员函数以普通方式进行测试,则该类与这些类不同。(如果不止一个函数需要这样做,这些模拟类可以针对每个函数、每个类和/或一个用于自由函数、每个库、一个用于所有函数;但是您需要设置它。)


不能将模拟方法2与静态方法一起使用。 您可以在B中定义一个只调用RetrieveJsonData的私有方法:

Class B
{
public:
   bool Method1 (std::string name) {
      Json::Value sampleJsonData;
      return retriveJsonData(name, sampleJsonData); };
private:
   bool retriveJsonData(std::string name, Json::Value& responseJsonData) {
      return A::retriveJsonData(name, responseJsonData); };
};
然后,您可以编写一个用于测试的测试类,而不是B:

Class Test_B : public B
{
   MOCK_METHOD2( retriveJsonData, bool(std::string name, Json::Value& responseJsonData));
};

不能将模拟方法2与静态方法一起使用。 您可以在B中定义一个只调用RetrieveJsonData的私有方法:

Class B
{
public:
   bool Method1 (std::string name) {
      Json::Value sampleJsonData;
      return retriveJsonData(name, sampleJsonData); };
private:
   bool retriveJsonData(std::string name, Json::Value& responseJsonData) {
      return A::retriveJsonData(name, responseJsonData); };
};
然后,您可以编写一个用于测试的测试类,而不是B:

Class Test_B : public B
{
   MOCK_METHOD2( retriveJsonData, bool(std::string name, Json::Value& responseJsonData));
};

不改变B类源代码是不可能的吗?不是这样的。否则,您可以在中有一个标志,使其执行模拟行为或正常行为。。。但这意味着一个小的分支成本+在某种程度上混合测试和prod代码。如果不更改class B源代码,这是不可能的吗?不是这样的。否则,您可以在中有一个标志,使其执行模拟行为或正常行为。。。但这在某种程度上意味着一个小的分支成本+混合测试和prod代码。我做过的一件事是“伪造”一个真正的静态或自由函数的定义(这里是
a::retrieveJsonData
)以重定向到一个单例模拟对象。(如果您已经将函数“伪造”为存根,以使B.o链接、更改或删除并替换该定义。)我可能可以稍后对此给出答案。我所做的一件事是“伪造”真实静态或自由函数的定义(此处
a::retrieveJsonData
)以重定向到单例模拟对象。(如果您已经将函数“伪造”为存根,以使B.o链接、更改或删除并替换该定义。)我稍后可能会对此给出答案。