Search code examples
c++apimockingvirtualpimpl-idiom

Mocking classes that use Pimpl pattern


Let's say, I create a library libFoo that exposes an API this class

class Book
{
    public:

    Book(string const& title, string const& author);
    string const& title() const;
    string const& author() const;

    private:
    struct Implementation;
    std::shared_ptr<Implementation> impl_;
};

The use of pimpl pattern is required. Later on, I realize that the users of my public class Book might want to mock it while they write unit tests for their own code. Now they need to shadow Book class since it does not have virtual methods.

So, I want to make Book class easily mockable. For that, we have the virtualization or the templatization (curiously recurrent design pattern or hi-perf dependency injection). What would be the advantage of each one in the context of a Pimpl pattern? For me it looks kind of wrong to have virtual methods on a class that implements the Pimpl pattern. On the other hand, the virtualization of the public API of libFoo will make the library mockable with minimum changes. What are the 'gotchas' waiting for me if I choose virtualization and Pimpl?

class Book
{
    public:

    Book(string const& title, string const& author);
    virtual string const& title() const;
    virtual string const& author() const;

    private:
    struct Implementation;
    std::shared_ptr<Implementation> impl_;
};

Solution

  • Pimpl is 100% about the implementation, it doesn't affect the interface at all.

    Mocking is about keeping the interface and swapping the implementation.

    There is no overlap. For mocking, it makes no difference how the class you're mocking is implemented.


    You could try to do something funny, like making the Implementation class virtual. That would be quite surprising and unexpected for the maintenance developers, so I strongly advise against that. Treat pimpl classes like every other class.