Closed zhlongfj closed 1 year ago
Hi. Can you please give a more complete example,, which includes the classes you are using?
//ITimeLineSchedulerCore1.h
class ITimeLineSchedulerCore1 { public:
virtual ~ITimeLineSchedulerCore1() {}
virtual void func() = 0;
};
//TimeLineSchedulerCore1.h
class TimeLineSchedulerCore1 : public ITimeLineSchedulerCore1 { public:
virtual ~TimeLineSchedulerCore1() {}
void func() {}
};
//TimeLineScheduler1.h
class ITimeLineSchedulerCore1;
class TimeLineScheduler1
{
public:
TimeLineScheduler1(std::unique_ptr
//TimeLineScheduler1.cpp
TimeLineScheduler1::TimeLineScheduler1(std::unique_ptr
}
TimeLineScheduler1::~TimeLineScheduler1() = default;
//timelinescheduler1_tests.cpp
using namespace std; using namespace fakeit;
SCENARIO("TimeLineScheduler") {
GIVEN("") {
Mock
WHEN("") {
THEN("") {
}
}
}
}
The code above will crash in VS2019, but the commented code is ok
Hi there. I think when you are copy and pasting into github must be removing the template parameters. I think you need to surround the code in triple `
``` some code more code ```
which gives this
some code
more code
//itimelineschedulercore1.h
#pragma once
class ITimeLineSchedulerCore1
{
public:
virtual ~ITimeLineSchedulerCore1() {}
virtual void func() = 0;
};
//timelineschedulercore1.h
#pragma once
#include <memory>
#include "itimelineschedulercore1.h"
class TimeLineSchedulerCore1 : public ITimeLineSchedulerCore1
{
public:
virtual ~TimeLineSchedulerCore1() {}
void func() {}
};
//timelinescheduler1.h
#pragma once
#include <memory>
#include "itimelinescheduler.h"
class ITimeLineSchedulerCore1;
class TimeLineScheduler1
{
public:
TimeLineScheduler1(std::unique_ptr<ITimeLineSchedulerCore1> schedulerCore);
~TimeLineScheduler1();
private:
std::unique_ptr<ITimeLineSchedulerCore1> _schedulerCore;
};
//timelinescheduler1.cpp
#pragma once
#include <memory>
#include "timelinescheduler1.h"
#include <xutility>
#include "itimelineschedulercore1.h"
TimeLineScheduler1::TimeLineScheduler1(std::unique_ptr<ITimeLineSchedulerCore1> schedulerCore)
: _schedulerCore(std::move(schedulerCore))
{
}
TimeLineScheduler1::~TimeLineScheduler1() = default;
//timelinescheduler1_tests.cpp
#include "fakeit.hpp"
#include <memory>
#include "timelinescheduler1.h"
#include "timelineschedulercore1.h"
using namespace std;
using namespace fakeit;
SCENARIO("TimeLineScheduler") {
GIVEN("") {
Mock<ITimeLineSchedulerCore1> schedulerCoreMock;
auto schedulerCore = unique_ptr<ITimeLineSchedulerCore1>(&schedulerCoreMock.get(), {});
//auto schedulerCore = (unique_ptr<ITimeLineSchedulerCore1>)make_unique<TimeLineSchedulerCore1>();
auto scheduler = std::make_unique<TimeLineScheduler1>(move(schedulerCore));
WHEN("") {
THEN("") {
}
}
}
}
For VC++ I get the same behaviour. (also note, I've configured my project for Edit and Continue, as per the instructions).
I've found I always need to do this.
Mock<IMyInterface> myMock;
Fake(Dtor(myMock));
std::unique_ptr<IMyInterface> pObject(&myMock.get());
Also these two statements are the same as far as I understand
auto schedulerCore = unique_ptr<ITimeLineSchedulerCore1>(&schedulerCoreMock.get(), {});
auto schedulerCore = unique_ptr<ITimeLineSchedulerCore1>(&schedulerCoreMock.get());
unique_ptr is not the same as shared_ptr, and so this is just an instance of the destructor object whose type in this case is std::default_delete, and so {}
will just result in the default constructor of std::default_delete.
shared_ptr doesn't have the delete as a type, and you can just pass in a lambda as an arg.
See https://en.cppreference.com/w/cpp/memory/unique_ptr
So it seems we always need to mock the deconstructor, just like we need to mock any other called virtual function, though it would probably be better if it had a default implementation which threw as well (like other called but non-mocked virtual functions.
Not sure if there is the same behaviour on other platforms.
Looking close at the header, it seems it should work, but seems it doesn't, or no longer works for VC++ - at least for v142/2019 compiler (even with Edit and Continue)
void unmockedDtor() {}
void unmocked() {
ActualInvocation<> invocation(Invocation::nextInvocationOrdinal(), UnknownMethod::instance());
UnexpectedMethodCallEvent event(UnexpectedType::Unmocked, invocation);
auto& fakeit = getMockImpl(this)->_fakeit;
fakeit.handle(event);
std::string format = fakeit.format(event);
UnexpectedMethodCallException e(format);
throw e;
}
It works, thanks
Anyway, I think it's not meant to crash by default. It should call unmockedDtor()
It seems it set's it up by default, but then makes a new VTable for the specific object but doesn't copy it across. Here is a fix: https://github.com/eranpeer/FakeIt/pull/289
@FranckRJ Did we want to mark this as closed now, given the fix, or are you waiting for the release or feedback?
Usually I close the issues after testing on my setup that the fix did in fact fix them (when it's something that I can reproduce). I haven't yet been able to test it because I didn't have my hands on a VS setup, but I will be able soon.
I've added unit tests, but it seems unit tests they aren't yet running on CI for VS (or if they are, the results aren't shown)
Fixed by #289 in FakeIt 2.3.1.
//Constructing real class is fine unique_ptr scheduler = make_unique((unique_ptr)make_unique());
//Moc class caused exception Mock schedulerCoreMock;
unique_ptr scheduler = make_unique(unique_ptr(&schedulerCoreMock.get(), {}));
//TimeLineScheduler constructor and destructor TimeLineScheduler::TimeLineScheduler(std::unique_ptr schedulerCore)
:_playingMediaEntities(std::make_shared())
, _schedulerCore(move(schedulerCore))
{
_schedulerCore->setPlayingMediaEntities(_playingMediaEntities);
}
TimeLineScheduler::~TimeLineScheduler() = default;
//Exception info: 0x0000000000000000 Exception raised at TimelineUnitTest.exe: 0xC0000005: Access conflict occurred at execution location 0x0000000000000000.
//Call stack: