【问题标题】:Break static variable dependency using Link Seam in C++在 C++ 中使用 Link Seam 打破静态变量依赖关系
【发布时间】:2018-04-20 22:52:20
【问题描述】:

我正在尝试为函数编写单元测试。这个函数是静态的,并且在一个文件中,比如 FileA.cpp,虽然它不是任何类的成员。

在 FileA.cpp 中还定义了一个静态变量。 在另一个文件中说 FileB.cpp 有这个静态变量的用法。

我现有的单元测试代码没有引用 FileA.cpp,因为到目前为止还没有对其功能进行测试。然而,它确实测试了 FileB.cpp 的功能。为了方便这个静态变量引用,在单元测试项目的 Main.cpp 中定义了一个假变量(我使用的是 GoogleTest 框架)。

但现在我需要测试 FileA.cpp。当我在 Makefile 中添加文件时,我收到此静态变量的“多重定义”错误。

我尝试在 Production 和 Testing 项目中分别引入一个同名的 .h 文件(比如 GlobalVars.h)并将变量移到那里,但它似乎并没有欺骗编译器。测试项目中的 FileA.cpp 实例仍然尝试访问生产代码的 GlobalVars.h,我再次得到双重定义。

有什么想法可以打破这种依赖关系吗?

【问题讨论】:

    标签: c++ unit-testing dependencies refactoring legacy-code


    【解决方案1】:

    您应该使用在匿名命名空间内定义的变量,而不是静态变量。这些可以用作静态全局变量将在翻译单元中,但它们的优点是在翻译单元之外不可见,不违反单一定义规则。

    // a.cpp
    static int count = 0;
    void f() { ++count; }
    
    // b.cpp
    static int count = 100; // breaks ODR
    int g() { return count--; }
    

    变成

    // a.cpp
    namespace { int count = 0; }
    void f() { ++count; }
    
    // b.cpp
    namespace { int count = 100; } // OK
    int g() { return count--; }
    

    进一步阅读:

    【讨论】:

    • 根据您链接到的 SO question,使用静态变量和在匿名命名空间中声明的变量没有本质区别。
    • "(...)在这种情况下,使用静态或未命名的命名空间本质上是两种做同样事情的方式。(...)"
    • @Clearer intent(目的)是相同的,但有细微的差别。就是这么说的。
    • 除非我记错了,在上面的例子中,每个文件都会影响它自己的count。但这不是我想要的。该变量必须在生产代码的文件之间保持共享。当此代码用于单元测试时,应该使用假静态变量。我知道它很难看,但我(还)没有支持重构的单元测试,我的实际任务也不能证明大规模更改是合理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 2011-06-06
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多