Like unit test if personal variable has changed

Say 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 correct way to do this unit test? How can I check if the closed example_var has changed?

+8
c ++ unit-testing testing mocking googletest
source share
5 answers

Short answer: Do not do this.

Your test should only test on the public interface. Let me try to explain with code:

 class Adder { int a,b; public: Adder() : a(0),b(0) {} void set(int x,int y) { a=x;b=y; } int get() { return a+b; } }; 

and a test (suppose we had access to a and b at some point):

 void testAdder(){ Adder add; int a = 1; int b = 2; add.set(a,b); ASSERT_EQUALS(add.a,a); ASSERT_EQUALS(add.b,b); ASSERT_EQUALS(add.get(),a+b); } 

Suppose you already distributed the code, and someone uses it. He would like to continue using it, but complains about too much memory consumption. To fix this problem is simple, keeping the same public interface:

 class Adder { int c; public: Adder() : c(0) {} void set(int x,int y) { c = x+y; } int get() { return c; } }; 

It was easy, but the test failed :(

Conclusion Testing the details of a private implementation hits the target of testing, because every time you change the code, it is likely that you also need to โ€œfixโ€ the test.

+10
source share

This is a bad approach for testing private variables / methods. But if you need, there are many options:

  • You can make your test class as a friend of ExampleClass

  • You can capture information using the moc object

+4
source share

If you want to access example_val , you can do one of two things. First, 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. } 

Alternatively, you can simply add a recipient to your ExampleClass to access the variable, for example:

 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 access to private class variables is usually not recommended.

+2
source share

Itโ€™s just that you simply implement the get function for this private variable that you want to receive.

 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 name 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 a testExampleMethod friend function (the friend function can access private variables of the friends class, even if this is 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, the first example would be more appropriate, but if you cannot change ExampleClass , you can disable access control for gcc - -fno-access-control .

+2
source share

A few options that I can think of:

1) Make a test code of a friend class. In this way, he can access private members.

2) Add a getter to the class, which is under the #ifdef Testing directive, which is defined only when creating the test version (or put public: under this macro and private: in the #else branch).

3) #define private public when creating a test (no, not really).

4) Use the gcc -fno-access-control flag when creating the version for testing, so that everything is public (if you use gcc).

5) Just pass the test from outside the class and instead add the appropriate static_assert s / assert to the class itself to check the invariants.

6) Do not. Just stick with open interface testing.

Hope that helps :-)

+2
source share

All Articles