我目前正在使用仅具有静态功能的另一个类的课程。

一切都很好,直到我尝试测试课程。

这是问题的简单代码示例:

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类正常工作(已经通过其单位测试进行了测试),我想检查 跑步 在B类中的功能。

我的第一个选择是为内部类创建模拟(在此示例 - A类)中,但是在这种情况下,它不会从A中继承任何东西,因为它只有静态功能。

我的第二个选项是将B内部私人功能中的类呼叫封装,以便我可以控制其返回值(尽管选择此选项会使良好的好处变得更加复杂)。

我对你的问题是: 是否有更好的方法来测试取决于静态类/功能的C ++类,而不是我当前的选项?

提前致谢,

塔尔。

有帮助吗?

解决方案

在类似情况下,我在单位测试方面取得了成功,通过重构对静态功能的参考(在我的情况下是外部依赖性)中的新私人功能,并在经过测试的存根上覆盖它们,因此我可以推荐这种方法

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

其他提示

如果您不使用单片测试套件,那么它就很容易。我认为您在B.CPP中的A.CPP和B类中有A类,并且B的测试在B_Test.cpp中。

创建一个称为a_mock.cpp的文件

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

然后,在编译B_Test文件时,只需与A_MOCK.O链接,而不是AO。

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

您可以将指针传递到该函数的指针到类A的构造函数。然后,进行测试,您可以将一些指针传递给模拟功能,在其中您可以做任何您想做的事。

为什么静态功能?我建议不要使它变得静态。

然后,您可以为A类创建一个界面(在C ++中,这意味着只有纯虚拟功能标头的类)名为Ainterface。 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;
}

测试代码

class MockClassA : public AInterface
{
    String getSometing() {
        return String("Whatever I want. This is a test");
    }
}   

void test ()
{
   // "MockClassA" would just be "A" in regular code
   auto instanceOfB = B(MockClassA());

   String returnValue = instanceOfB.runSomething("something");
   :
   :
}

我会说:“伙计,有些人对单位测试进行得太遥远!”

只需将两个类作为一个单元测试即可。 A类都将A类编码为B类。

您应该通过模板上课,并明确导出该实例(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!
    }
}

模板的奇观永远不会让我惊讶。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top