2010-11-01 96 views
3

我目前正在使用另一个只有静态函数的类的类。测试依赖于另一个类的静态函数的类

一切工作正常,直到我尝试测试我的课程。

这是问题的一个简单的代码例如:

class A { 
    static String getSometing() { 
     return String("Something: ") + heavyCalculation().asString(); 
    } 
} 

class B { 
    B() {} 
    ~B() {} 
    String runSomething(const String& name) { 
     if(name.equals("something")) { 
      return A::getSomething(); 
     } else { 
      return "Invalid name!"; 
     } 
    } 
} 

假设类A是否正常工作(并且已经被它的单元测试测试),我想检查在类runSomething功能B.

我的第一选择是创建内部类(在这个例子 - A类)嘲笑,但在这种情况下,它会给我没什么可从A继承,因为它只有静态功能。

我的第二个选择是封装在内部B私有函数的类的调用,所以我可以控制自己的返回值(虽然选择此选项将使好一点点更复杂)。

我对你的问题是:是否有更好的方法来测试C++类取决于比我目前的选择静态类/功能?

由于提前,

塔尔。

回答

3

我已经在类似的情况下通过重构静态函数的引用(在我的情况下它是外部依赖)到新的私有函数并覆盖它们在测试存根上的单元测试中取得成功,所以我可以推荐这种方法

如果重构功能保持私密,他们不应该大大的设计的复杂性影响,他们应该是足够小,不会产生负面的代码的可读性产生影响。

0

我会说,“男人,有些人采用单元测试的方式太过分了!”

只需将两个类作为一个单元进行测试即可。无论如何,A类都被硬编码到B类中。

+2

如果需要30秒来执行该静态函数会怎么样? – 2010-11-02 08:41:25

+0

@VJo:那么你担心解决这个问题。如果执行该功能需要0.0030秒,则您只需花费大量测试写入时间。 – 2010-11-03 21:20:27

-1

你应该通过模板走班,并明确导出实例化(B<A>),以避免连接问题,如果张贴以前没有所有内联。这样,您可以根据需要插入其他类以用于测试,无论如何都是很好的练习。我也很好奇为什么你的例子看起来像Java一样 - 我必须在确定它实际上是 C++之前阅读过它大约五次。

template<typename T> class BImpl { 
    String runSomething(const String& name) { 
     if(name.equals("something")) { 
      return T::getSomething(); 
     } else { 
      return "Invalid name!"; 
     } 
    } 
}; 
typedef BImpl<A> B; // Just plugs in to existing code. 

现在,即使无法继承它,现在您也可以用模拟类替换A。事实上,这也可以用另一种方式扩展 - CRTP。

class A : public BImpl<A> { 
    String getSomething() { 
     // Now it's non-static! IT'S A MIRACLE! 
    } 
} 

模板的奇迹永远不会停止让我惊叹。

1

如果你不使用单片测试套件,那么它很容易。我假设你有A.cpp中的A类和B.cpp中的B类,并且B的测试在B_test.cpp中。

创建一个名为A_mock的文件。cpp

class A 
{ 
    static String getSometing() { 
     return String("Expected Something"); 
    } 
}; 

然后编译你的B_test文件时,只需要链接到A_mock.o而不是A.o。

g++ -Wall B_test.cpp B.cpp A_mock.cpp 
+0

这是可行的,而在非面向对象的代码中往往是唯一可以应用的方法。但是,它确实导致函数的覆盖与实际测试代码分开,导致更复杂的维护方案 - 在原始编码器之后出现的人不一定会认为要查看makefile以找出正在调用的静态函数。 – dlanod 2010-11-02 21:16:59

0

你可以一个函数指针传递给类A,然后进行测试的构造函数,你可以传递一些指针模拟功能,在这里你可以做任何你想要的。

0

为什么静态函数?我会建议不要把它变成静态的。

然后,您可以创建一个名为AInterface的类A(在C++中,这意味着一个只有纯虚函数头的类)的接口。 A类将实现(继承)AInterface并实现这个虚函数。

然后将指向此接口的指针传递给B类的构造函数,并将其存储在名为m_A的成员变量中。然后在你的测试中,创建实现AInterface的MockClassA。将MockClassA传入B类构造函数,并将m_A设置为输入。

class AInterface 
{ 
    virtual String getSomething() = 0; 
} 

class A : public AInterface 
{ 
    String getSometing() { 
     return String("Something: ") + heavyCalculation().asString(); 
    } 
} 

class B 
{ 
    B(AInterface A) : m_A(A) {} 
    ~B() {} 
    String runSomething(const String& name) { 
     if(name.equals("something")) { 
      return m_A::getSomething(); 
     } else { 
      return "Invalid name!"; 
     } 
    } 
    AInterface m_A; 
} 

void test() 
{ 
    auto instanceOfA = std::make_shared<A>(); 
    auto instanceOfB = std::make_shared<B>(instanceOfA); 

    String returnValue = instanceOfB.runSomething("something"); 
    : 
    : 
} 
相关问题