Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test accessing private variables

I have a unit test class Tester; I want it to access private fields of a Working class.

class Working {
    // ...
    private:
    int m_variable;
};

class Tester {
    void testVariable() {
        Working w;
        test( w.m_variable );
    }
}

I have the following options:

  • make m_variable public - ugly
  • make method test_getVariable() - overcomplicated
  • add friend class Tester to Working - then Working "knows" about the Tester explicitly, which is not good

My ideal would be

class Working {
    // ...
    private:
    int m_variable;

    friend class TestBase;
};

class TestBase {};

class Tester : public TestBase {
    void testVariable() {
        Working w;
        test( w.m_variable );
    }
}

where Working knows about TestBase but not each test... but it does not work. Apparently friendship does not work with inheritance.

What would be the most elegant solution here?

like image 453
Jakub M. Avatar asked Dec 23 '11 17:12

Jakub M.


People also ask

How do you access private variables in test class?

Use the TestVisible annotation to allow test methods to access private or protected members of another class outside the test class. These members include methods, member variables, and inner classes. This annotation enables a more permissive access level for running tests only.

Can private variables be accessed?

We can access a private variable in a different class by putting that variable with in a Public method and calling that method from another class by creating object of that class.

Can tests access private methods?

And while you can test a private method by changing it to public, you shouldn't. Private methods are great for breaking logic into smaller parts. If a method gets too big, you should refactor it and break it down into private methods so it's easier to read. But you don't need to test those private methods individually.


2 Answers

I agree with Trott's answer, but sometimes you're adding unit tests to legacy code that wasn't designed for it. In those cases, I reach for #define private public. It's just in unit tests, and it's just for when refactoring is too expensive to bother. It's ugly, technically illegal, and very effective.

like image 69
Michael Kristofik Avatar answered Nov 03 '22 00:11

Michael Kristofik


Generally, your unit tests should not evaluate private variables. Write your tests to the interface, not the implementation.

If you really need to check that a private variable has a particular characteristic, consider using assert() rather than trying to write a unit test for it.

A longer answer (written for C# rather than C++, but the same principles apply) is at https://stackoverflow.com/a/1093481/436641.

like image 37
Trott Avatar answered Nov 03 '22 00:11

Trott