lefticus / cpp_weekly

The official C++ Weekly Repository. Code samples and notes of future / past episodes will land here at various times. PR's will be accepted in some cases.
The Unlicense
683 stars 26 forks source link

C++ unittests, best practices using mocks and stubs #104

Open elheck opened 2 years ago

elheck commented 2 years ago

Channel C++ Weekly

Topics

There are powerful unittesting, mocking and stubbing libraries out there like gtest and gmock and others, but in order to mock a existing class, it needs a pure virtual class to be cleanly mocked. Are there alternatives? Setting the behavior of mocks is often done in nested lambdas like so:

ON_CALL(*builder_, Create).WillByDefault([&](propulsion::PropulsionHardwareConfig &) {
      std::unique_ptr<NiceMock<propulsion::MotorMock>> motor = std::make_unique<NiceMock<propulsion::MotorMock>>();
      ON_CALL(*motor, SetSpeedInPercent).WillByDefault(Return(types::DriverStatus::OK));
      ON_CALL(*motor, SetSpeedInPercent(66.6)).WillByDefault(Return(types::DriverStatus::HAL_ERROR));
      ON_CALL(*motor, GetCurrentSpeedInPercent).WillByDefault([&]() {
        return float_factory_.GetSpeed();
      });
      return motor;

Is there a cleaner way?

Length

10-20

dosisod commented 1 year ago

@elheck You might want to look into FakeIt, which is a really simple C++ mocking/stubbing library I've used in the past. It still requires virtual classes though.

elheck commented 1 year ago

Thanks I will have a look

avimalka commented 1 year ago

There is a very nice approach for C (but the idea is pretty generic) in a project called cmocka. The idea is to use the linker for wrapping the functions you wish to mock with --wrap flag and provide your version (Example) . It's very linker dependent, but there is a great benefit since you can mock everything regardless of how it's used, in addition you can mock system functions as well (open(), read() etc')