对于单元测试,是否有一种改变 const 变量值的黑客方法?

Gam*_*ads 2 c++ googletest const-cast c++11

我有一个 C++ 11 头文件,它的 const 值声明为my_const_value. 还有一个被调用的函数GetValue,它使用 const 值运行复杂的逻辑并返回一个预期值。

我想GetValue用不同的my_const_value.

我知道这是不可取的,但为了编写单元测试GetValue,我希望GetValue使用不同的my_const_value. C++ 中是否有一些hack-ish方法来改变const的值,即使它是一个const?

//MyHeader.hpp
namespace myheader {

const int my_const_value = 5;

int GetValue() {
    // In real-world, lets say below line of code is a complex logic that needs to be tested by a unit test
    return /my_const_value * 5) / 25;
}

}

#include "MyHeader.hpp"
#include <gtest/gtest.h>

TEST(MyHeaderTest, Testing_Something) {
    EXPECT_EQ(1, myheader::GetValue()); // This is okay

    // I want to test that in the future is the value of my_const_value changes to something else then 
    // myheader::GetValue returns the expected result. But of course, I cannot change my_const_value because it is a const.
    // Is there a way to hack around this for a unit test? Is there a way that I could still hack and change the value of my_const_value?
    myheader::my_const_value = 25;
    EXPECT_EQ(5, myheader::GetValue());
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以const_cast my_const_value使用 non_const 变量。但这在这里无济于事。如果有一些技巧可以my_const_value通过使用指针或其他东西来更改 的值,那将回答我的问题。

for*_*818 8

不。

更改声明为const调用未定义行为的值。为了说明,请考虑此代码

const int x = 4;
modify_const_somehow(x,42);   // "magically" assigns 42 to x
std::cout << x;
Run Code Online (Sandbox Code Playgroud)

可以打印任何东西。您可以4在控制台上看到或42,但"Hey you broke the rules, const cannot be modified"也是有效的输出。无论您如何修改x,代码都有未定义的行为。编译器不需要发出错误或警告,代码只是无效的,编译器没有被强制执行任何对它有意义的事情。

允许删除常量的唯一情况是对象实际上不是常量。听起来很奇怪不是吗?看这个例子:

const int x = 42;
int y = 100;

void foo(const int& a) {
    const_cast<int&>(a) = 4;
}

foo(x);  // undefined behavior !!
foo(y);  // OK !!
Run Code Online (Sandbox Code Playgroud)

解决您的问题的方法是编写可测试的代码。例如:

int GetValue(int value = my_const_value) {
    // In real world, lets say below line of code is a complex logic that needs to be tested by a unit test
    return (value * 5) / 25;
}
Run Code Online (Sandbox Code Playgroud)

如果您想保留原始签名,您也可以将其包装(如评论中所建议):

int GetValue_impl(int value) {
    return (value * 5) / 25;
}
int GetValue() {
    return GetValue_impl(my_const_value);
}
Run Code Online (Sandbox Code Playgroud)

现在您可以测试GetValue_implwhileGetValue使用常量。但是,我真的很想知道您为什么要测试一个不可能发生的情况。