1

I'm using gtest as my unit test framework. In my work, it's a common case that a public method modifies some private variables in the object. These variables stores the "states" of the object and has affects to the object's behavior. For example:

class ConferenceRoom {
public:
  void AddUser(const std::string& user_info);

  void OnDataReceived(uint32_t user_id, const std::string& message);

private:
  // Map[user_id] --> User
  std::unordered_map<uint32_t, User> user_map_;
};

I want to test the public method AddUser with various good/bad user_info, but I can't access the private variable user_map_ directly to check if this map is changed as I expected. I don't know what's the best practice for this case? I know some solutions:

  1. Using friend to access ConferenceRoom's private variable, this will make ConferenceRoom aware test code.
  2. Declare user_map_ as protected, and using TestRoom inherits ConferenceRoom, then check the map in TestRoom.
  3. Add a virtual private method const std::unordered_map<uint32_t, User>& GetUserMap() const; using TestRoom inherits ConferenceRoom and overrides this virtual method, then access private user_map_ with GetUserMap.

I'm sure there must be some other solutions for this case. In my mind, the solution should be isolate class ConferenceRoom with test code, and the class ConferenceRoom can be delivered to use clearly without any strange code. What your best practice?

jasonxia
  • 321
  • 1
  • 8
  • 1
    If accessing private variable is the motive, then it's a possible duplicate of [Can I access private members from outside the class without using friends?](https://stackoverflow.com/q/424104/514235)? – iammilind Jan 02 '20 at 03:09
  • @iammilind, thanks for your information. I think that post is discussing another different topic. – jasonxia Jan 02 '20 at 03:15
  • Private data should be a implementation detail. Can't you test the public interface? – Jarod42 Jan 02 '20 at 08:15
  • yes, I want to test the **public** interface `AddUser()`, but I don't know how to check whether `AddUser()` works as design if I can't access the private variable `user_map_`. And no other objects in the system needs to access `user_map_` except the unit test code, so I think I should not add a public access method such as `UesrMap()` @Jarod42 – jasonxia Jan 11 '20 at 11:24
  • You don't. That's testing the implementation. You should be testing the behaviour. – user207421 Jan 11 '20 at 12:21

1 Answers1

-1

Using a small template magic code as demonstrated in this answer already, you may access the private variables directly without modifying the source.

For your code, you have to do following:

ALLOW_ACCESS(ConferenceRoom, user_map_, std::unordered_map<uint32_t, User>); // setup
// ... class declarations ...
ConferenceRoom object;
auto& user_map_ = ACCESS(object, user_map_);
// use `user_map_`

Demo.

Community
  • 1
  • 1
iammilind
  • 68,093
  • 33
  • 169
  • 336