Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test if a private variable has changed

Let's say that I have this class in C++:

class ExampleClass{
private:
    int example_var;
public:
    void exampleMethod(){
         example_var = other_value; // other value will be always different
    }
}

How can I unit test exampleMethod()? I would like to do something like this:

void testExampleMethod(){
    ExampleClass obj;
    int before_call_value = obj.example_var;
    obj.exampleMethod();
    int after_call_value = obj.example_var;
    ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}

But example_var is private.

So, what is the right way to do this unit test? How can I test if a private example_var has changed?

like image 782
Maximetinu Avatar asked Aug 15 '17 17:08

Maximetinu


People also ask

Can we unit test private methods?

Why We Shouldn't Test Private Methods. As a rule, the unit tests we write should only check our public methods contracts. Private methods are implementation details that the callers of our public methods are not aware of. Furthermore, changing our implementation details should not lead us to change our tests.

Can private variables be changed?

The mangling rules are designed mostly to avoid accidents but it is still possible to access or modify a variable that is considered private.

Should private methods have unit tests?

Unit Tests Should Only Test Public Methods The short answer is that you shouldn't test private methods directly, but only their effects on the public methods that call them. Unit tests are clients of the object under test, much like the other classes in the code that are dependent on the object.


3 Answers

It is bad approach to test private variable/methods. But if you need there are a lot of options:

  1. You can make Your test class as friend of ExampleClass

  2. You can grab information using moc object

like image 118
arturx64 Avatar answered Oct 25 '22 20:10

arturx64


If you want to access example_val, there are one of two things you can do. The first is by making testExampleMethod() a friend method, as follows:

class ExampleClass{
private:
    int example_var;
public:
    void exampleMethod(){
         example_var = other_value; // other value will be always different
    }
    friend void testExampleMethod(); //Now you can use the function as is.
}

On the other hand, you could just add a getter to your ExampleClass to access the variable, such as the following:

class ExampleClass{
private:
    int example_var;
public:
    void exampleMethod(){
         example_var = other_value; // other value will be always different
    }
    inline void getExampleVar() const { return example_var; }
}

And then change testExampleMethod() to:

void testExampleMethod(){
    ExampleClass obj;
    int before_call_value = obj.getExampleVar();
    obj.exampleMethod();
    int after_call_value = obj.getExampleVar();
    ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}

I would honestly use the second method, since accessing a class's private variables is generally not recommended.

like image 25
Arnav Borborah Avatar answered Oct 25 '22 21:10

Arnav Borborah


You just simply implement get function for that private variable you want to get.

class ExampleClass{
private:
    int example_var;
public:
    void exampleMethod(){
         example_var = other_value; // other value will be always different
    }

    int GetExampleVar(){
         return example_var;
    }
}

And call it like

void testExampleMethod(){
    ExampleClass obj;
    int before_call_value = obj.GetExampleVar();
    obj.exampleMethod();
    int after_call_value = obj.GetExampleVar();
    ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}

Or make testExampleMethod friend function (friend function can access private variables of friend class even if its not its method).

class ExampleClass{
private:
    int example_var;
public:
    void exampleMethod(){
         example_var = other_value; // other value will be always different
    }

    friend void testExampleMethod();
}

In my opinion first example would be more suitable, but if you cannot modify ExampleClass, you can turn off access control for gcc -- -fno-access-control.

like image 23
kocica Avatar answered Oct 25 '22 20:10

kocica