c++c++11googletestconst-cast

For unit tests, is there a hackish way to change the value of a const variable?


I have a C++ 11 header which has a const value declared as my_const_value. And a function called GetValue that runs a complex logic using the const value and returns an expected value.

I want to unit test GetValue with different values of my_const_value.

I know this is not advisable but for writing a unit test for GetValue, I wish to test GetValue with different values of my_const_value. Is there some hack-ish way in C++ to change the value of a const even if it a 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());
}

I know that I could const_cast my_const_value to a non_const variable. But that wouldn't help here. If there is some hack to change the value of my_const_value by using a pointer or something, that would answer my question.


Solution

  • I know you are looking for a way how to cast the const away, but I probably would go a different way.

    You say in your comment:

    Well. I have given my reason. I am testing the logic in GetValue. I have declared my_const_value as a const but that can be changed from 5 to something else in future when someone changes the value in future.

    If a variable is const and particiaptes in a expresion within a function without being passed to it, then those changes normally shouldn't happen at a regular basis, and should not be expected. If you consider the myheader::my_const_value a config value, and as of that might change anytime, then it should be passed to the function in which it is used in an expresion.

    So from the perspective of testing I agree with what idclev 463035818 suggest in the answer, to split the function in two parts in one testable part with a prameter and one that uses a constant.

    One test that tests how the code currently should behave (what constant it should have)

    TEST(MyHeaderTest, Testing_Something1) {
        EXPECT_EQ(5, myheader::my_const_value)
        EXPECT_EQ(1, myheader::GetValue());
        
    }
    

    And one for the generic test:

    TEST(MyHeaderTest, Testing_Something2) {
        EXPECT_EQ(1, myheader::GetValue_impl(5));
        EXPECT_EQ(5, myheader::GetValue_impl(25));
        // …
    }
    

    That way you have the generic test if the caluclation used by GetValue works. And one if for the current verion of you code the value of myheader::GetValue() is the expected one.