I have the following object that I want to mock:
class Esc {
public:
Esc() = default;
virtual ~Esc() {}
virtual int GetMaxPulseDurationInMicroSeconds() const noexcept{
return 100;
}
};
I wrote this mock:
class MockEsc : public Esc {
public:
MockEsc(){}
MockEsc(const MockEsc&){}
MOCK_METHOD(int, GetMaxPulseDurationInMicroSeconds, (), (const, noexcept, override));
};
And this is the unit under test which calls the aforementioned Esc.GetMaxPulseDurationInMicroSeconds()
method
class LeTodar2204{
public:
LeTodar2204() = delete;
explicit LeTodar2204(std::unique_ptr<Esc> esc) : esc_(std::move(esc)){}
int CallingMethod(){
int a = esc_->GetMaxPulseDurationInMicroSeconds();
return a;
}
private:
std::unique_ptr<Esc> esc_;
};
In the SetUp of my testfixture I want to set my mock to return a 1 and inject it into the unit under test.
class Letodar2204Tests : public ::testing::Test {
protected:
Letodar2204Tests() {}
virtual void SetUp() {
EXPECT_CALL(esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
unit_under_test_ = std::make_unique<LeTodar2204>(std::make_unique<MockEsc>(esc_));
}
MockEsc esc_;
std::unique_ptr<LeTodar2204> unit_under_test_;
};
Now in the test I call the method that should call the mocked method, but GetMaxPulseDurationInMicroSeconds
of my mocked object only returns 0 (aka the default value) and warns me about the uninteresting function call.
This is the test
TEST_F(Letodar2204Tests, get_pulse_duration) {
EXPECT_CALL(esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
auto duration = unit_under_test_->CallingMethod();
ASSERT_EQ(duration, 1);
}
What am I missing?
Because you are effectively assigning expectation to an object which you'll be copying anyway. esc_
default ctor is going to be called once Letodar2204Tests
is instantiated. Now, in SetUp
you assign an expectation on class' field esc_
, and then, basing on esc_
create a brand new object (on the heap, using make_unique
) using its copy-ctor. Expectations are not going to be magically copied as well. I believe you should store an unique_ptr<MockEsc> esc_
as a class' field, instantiate it on heap within SetUp
and inject to LeTodar
:
class Letodar2204Tests : public ::testing::Test {
protected:
Letodar2204Tests() {}
virtual void SetUp() {
esc_ = std::make_unique<MockEsc>();
EXPECT_CALL(*esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
unit_under_test_ = std::make_unique<propulsion::LeTodar2204>(esc_);
}
std::unique_ptr<MockEsc> esc_;
std::unique_ptr<propulsion::LeTodar2204> unit_under_test_;
};
Here, you are implicitly calling copy-ctor: std::make_unique<MockEsc>(esc_)
You could do a simple test: mark copy ctor in MockEsc 'deleted' and you'll see that your project no longer compiles (at least it shouldn't be :D)