I am working on class unit testing and encountered this problem - a premature deletion of Device* device
/mock:
Here is my SUT:
Effect::~Effect()
{
for (auto it = infoList.begin(); it != infoList.end(); ++it)
{
(*it)->device->Remove(this, (*it)->position);
delete *it;
}
infoList.clear();
}
HRESULT Effect::Add(Device* device, ULONG position)
{
Info* info = new Info;
info->device = device;
info->position= position;
auto result = device->Add(position);
if (result == E_FAIL) return E_FAIL;
//some other methods being called from 'device'
infoList.push_back(info);
}
And my test:
class EffectTest: public ::testing::Test
{
public:
void SetUp()
{
sut_ = std::make_unique<Effect>();
deviceMock_ = std::make_shared<DeviceMock>();
}
protected:
std::unique_ptr<Effect> sut_;
std::shared_ptr<DeviceMock> deviceMock_;
};
TEST_F(EffectTest, Add)
{
EXPECT_CALL(*deviceMock_, Add(_).WillRepeatedly(Return(S_OK));
EXPECT_CALL(*deviceMock_, Remove(_, _)).WillRepeatedly(Return(S_OK));
sut_->Add(deviceMock_.get(), 90);
}
Since I am only passing a raw pointer (mock) deviceMock_.get()
in Effect::Add(), reference count is not incremented. Test tears down earlier than the actual SUT so deviceMock_ is already deleted when Effect destructor is called. My problem is.. device is still being called in Effect's destructor and therefore causes a crash:
(*it)->device->Remove(this, (*it)->position);
Any thoughts on what I can do to force the deviceMock_
to stay alive when ~Effect
is called?
Can I force deviceMock_ reference count to increment only with the raw pointer Device* device
??
Please do note though that I CANNOT CHANGE THE FUNCTION SIGNATURE OF:
HRESULT Effect::Add(Device* device, ULONG position)
Since this is an API.
Help please! Thanks!
Reverse the order of sut_
and deviceMock_
in EffectTest
:
class EffectTest: public ::testing::Test
{
public:
void SetUp()
{
sut_ = std::make_unique<Effect>();
deviceMock_ = std::make_shared<DeviceMock>();
}
protected:
std::shared_ptr<DeviceMock> deviceMock_;
std::unique_ptr<Effect> sut_;
};
Member variables are deleted from bottom to top. Changing this will cause Effect to be deleted before DeviceMock.