Search code examples
c++unit-testingexceptionconstants

Can you properly test a const member function If you include exception safety inside that function without having to comment it out after?


Question How does one test a const member function?

Goal:

Unit test a const subscript operator and get a passing test. In other words can I avoid writing a test; have a compiler throw an error to prove success, then avoid the need to comment the test out to allow proper compilation for the remainder of the tests?

My Attempts: My reasoning was if I test for is_const<>::value and is true I can throw an exception that would be caught by my unit test and allow the test to "Pass" do to failure to change value of element at location of subscript index.

my const subscript definition

   #include <type_traits>

   // operator [] const
    
    template <typename T>                               
    typename Vector<T>::const_reference
    Vector<T>::operator[](size_t index) const {
        if (size_ <= index || index < 0) {
            throw std::out_of_range("Index out of range.");
        }
        if constexpr(std::is_const<std::decltype(*this)>::value) {
            throw std::runtime_error("Cannot modify elements of a const Vector.");
        }
        return array_[index];
    }

my UnitTest

TEST(SubScriptConst) {
    const Vector<int> myVecConst = {0,1,2,3,4,5,6,7,8};
    try {
        myVecConst[2] = 4; // This will throw an exception?
    } 
    catch (const std::exception& ex) {
        std::cout << "SUCCESS | Caught exception: " << ex.what() << std::endl;
    }
    CHECK_EQUAL(myVecConst[2], 2);
}

The obvious. It does not work. I know its because of my lack of understanding the language. My assumptions are the compiler is checking the value assignment of a const before the code is executed and gives error. If I am able to I will be placing the try block inside a MACRO #ifdef for testing only and still allow the compiler to throw error when not testing.


Solution

  • If a class member function declered as const then it can't modify any class data members except the class data members which are declered mutable.

    This const behavior is enforced by compiler and not the C++ runtime. So if someone will try to modify a non-mutable data member in const member function then it will be a compile time error and not a runtime error. So you can skip writing such test cases.

    Following are some related excerpts from in C++ standard:

    [Note 1: Thus in a const member function, the object for which the function is called is accessed through a const access path. —end note]

    int s::f() const { return a; }

    The a++ in the body of s::h is ill-formed because it tries to modify (a part of) the object for which s::h() is called.

    This is not allowed in a const member function because this is a pointer to const; that is, *this has const type.