Here's my issue, I'd like to mock a class that creates a thread at initialization and closes it at destruction. There's no reason for my mock class to actually create and close threads. But, to mock a class, I have inherit from it. When I create a new instance of my mock class, the base classes constructor is called, creating the thread. When my mock object is destroyed, the base classes destructor is called, attempting to close the thread.
How does one mock an RAII class without having to deal with the actual resource?
Smart pointers use RAII to hide the manipulation of pointers, which are a lower level than business code, so RAII helps respect levels of abstraction in that case too. This is true for resource management in general, including database connection.
As the object gets initialized, it acquires the resource it owns. The object is then responsible for releasing the resource in its destructor. The owning object itself is declared on the stack. The principle that objects own resources is also known as "resource acquisition is initialization," or RAII.
RAII is associated most prominently with C++ where it originated, but also D, Ada, Vala, and Rust. The technique was developed for exception-safe resource management in C++ during 1984–89, primarily by Bjarne Stroustrup and Andrew Koenig, and the term itself was coined by Stroustrup.
Resource Acquisition Is Initialization or RAII, is a C++ programming technique which binds the life cycle of a resource that must be acquired before use (allocated heap memory, thread of execution, open socket, open file, locked mutex, disk space, database connection—anything that exists in limited supply) to the ...
You instead make an interface that describes the type, and have both the real class and the mock class inherit from that. So if you had:
class RAIIClass {
public:
RAIIClass(Foo* f);
~RAIIClass();
bool DoOperation();
private:
...
};
You would make an interface like:
class MockableInterface {
public:
MockableInterface(Foo* f);
virtual ~MockableInterface();
virtual bool DoOperation() = 0;
};
And go from there.
First of all, it is not necessarily an unreasonable thing that your classes might be well designed for their use, but poorly designed for testing. Not everything is easy to test.
Presumably you want to use another function or class which makes use of the class which you want to mock (otherwise the solution is trivial). Lets call the former "User" and the latter "Mocked". Here are some possibilities:
The last two may be your only recourse if you can not modify User or Mocked. If you can modify User and you believe that designing your code to be testable is important, then you should explore the first option before any of the others. Note that there can be a trade off between making your code generic/flexible and keeping it simple, both of which are admirable qualities.
The pimpl idiom might suit you as well. Create your Thread class, with a concrete implementation that it brings in underneath. If you put in the right #defines and #ifdefs your implementation can change when you enable unit testing, which means that you can switch between a real implementation and a mocked one depending on what you are trying to accomplish.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With