eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.23k stars 169 forks source link

Linker error: undefined reference to constructor and destructor #170

Closed zfields closed 5 years ago

zfields commented 5 years ago

Test Code:

#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <fakeit.hpp>

#include "system_publish_vitals.h"

namespace interface {
class Timer {
  public:
    virtual ~Timer (void) = 0;
    virtual bool changePeriod (const size_t) = 0;
    virtual void dispose (void) = 0;
    virtual bool isActive (void) = 0;
    virtual void reset (void) = 0;
    virtual void start (void) = 0;
    virtual void stop (void) = 0;
};
} // namespace interface

TEST_CASE("sending messages", "[publishVitals]") {
    system::VitalsPublisher<fakeit::Mock<interface::Timer> >::publish_fn_t mock_fn = [](void) -> int { return 0; };
    fakeit::Mock<interface::Timer> mock_timer;

    system::VitalsPublisher<fakeit::Mock<interface::Timer> > vp(mock_fn, mock_timer);

    SECTION("Called without parameters - Publishes message immediately") {
        CHECK(true);
    }
}

Constructor and Destructor signatures:

template <class Timer>
class VitalsPublisher {
  public:
    /**
     * @typedef publish_fn_t
     * @brief A function requiring no parameters and returning a \p system_error_t
     */
    typedef std::function<int(void)> publish_fn_t;

    /**
     * @brief Constructor
     *
     * @param[in] publish_fn The function used to send cloud messages
     * @param[in] timer The timer used to schedule the period
     */
    VitalsPublisher (
        publish_fn_t publish_fn,
        const Timer & timer
    );

    /**
     * @brief Destructor
     *
     * The destructor ensures the resources allocated during the
     * scheduling of events are returned to the system.
     */
    virtual
    ~VitalsPublisher (
        void
    );
...

Compile Instruction:

g++ system_publish_vitals.cpp publish_vitals.cpp -I ../../../third_party/catch2/catch2/single_include/ -I ../../../third_party/fakeit/fakeit/single_header/catch/

Linker Error:

CMakeFiles/publish_vitals.dir/publish_vitals.cpp.o: In function `____C_A_T_C_H____T_E_S_T____0()':
publish_vitals.cpp:(.text+0x25a88): undefined reference to `system::VitalsPublisher<fakeit::Mock<interface::Timer> >::VitalsPublisher(std::function<int ()>, fakeit::Mock<interface::Timer> const&)'
publish_vitals.cpp:(.text+0x25c6c): undefined reference to `system::VitalsPublisher<fakeit::Mock<interface::Timer> >::~VitalsPublisher()'
publish_vitals.cpp:(.text+0x25d74): undefined reference to `system::VitalsPublisher<fakeit::Mock<interface::Timer> >::~VitalsPublisher()'
collect2: error: ld returned 1 exit status

This is my first time with Fakeit, so I'm not certain I'm using it correctly or if I am experiencing a limitation of the framework? If this is a limitation, is there a workaround?

zfields commented 5 years ago

It appears this is a problem with my templating and not with Fakeit. I felt obligated to share the mistake here in case someone else begins down this path.