Factory Pattern w/ Gmock - c++

I have a interface where I am using the factory pattern to create an instance of the object and store it in a unique_ptr. I also have a MockInterface which I would like to use in my tests to not call the actual production code. However when I run my tests the production interface is called instead of the mock. What am I doing wrong??
Interface.hpp
class Interface
{
Interface() {};
virtual ~Interface() = default;
virtual int foo() = 0;
virtual int bar() = 0;
static std::unique_ptr<Interface> create();
};
Interface.cpp
#include "Interface.hpp"
#include "Impl.hpp"
std::unique_ptr<Interface> Interface::create()
{
return std::unique_ptr<Interface> { new Impl() };
}
Impl.hpp
class Impl : public Interface
{
Impl() {};
~Impl() {};
virtual int foo();
virtual int bar();
};
Impl.cpp
#include "Interface.hpp"
#include "Impl.hpp"
int Impl::foo()
{
return 2;
}
int Impl::bar()
{
return 2;
}
class MockInterface : public Interface
{
MockInterface() {};
~MockInterface() {};
MOCK_METHOD(int, foo, (), (override));
MOCK_METHOD(int, bar, (), (override));
}
lib.cpp
#include "Interface.hpp"
class Foo
{
public:
Foo() { inst = Interface::create(); }
virtual ~Foo() = default;
void some_function();
private:
std::unique_ptr<Interface> inst;
}
void Foo::some_function()
{
int foo_ret = inst->foo();
int bar_ret = inst->bar();
}
test.cc
std::unique_ptr<Interface> Interface::create()
{
std::unique_ptr<MockInterface> mock { new MockInterface() };
EXPECT_CALL(*mock, foo()).Times(1);
EXPECT_CALL(*mock, bar()).Times(1);
return mock;
}
TEST_F(fixture, test_foo)
{
// This will pass but I will get an error "mock object never deleted"
// Will also leave my terminal in a bad state
Foo *obj = new Foo();
obj->some_function();
// This will fail also leaving my terminal in a bad state
Foo obj2;
obj2.some_function();
}

some_function() calls Interface::create(), which has not been mocked, so it's still going to give you back a unique pointer pointing to an Impl object, not a MockInterface object.
To solve this you can either mock out Interface::create to have it return your mocked object, or have some_function receive a pointer/reference to Interface as a parameter instead of calling Interface::create itself. Then just pass it your mocked object.
The simplest way to mock the create function is to just redefine it for your tests. Exclude Interface.cpp from your test program since the function can only be defined once
std::unique_ptr<Interface> Interface::create()
{
std::unique_ptr<MockInterface> mock { new MockInterface() };
EXPECT_CALL(*mock, foo()).Times(1);
return mock;
}
TEST_F(fixture, test_foo)
{
some_function();
}
To provide different implementations for each test you can do something like this:
std::function<std::unique_ptr<Interface>()> creator;
std::unique_ptr<Interface> Interface::create()
{
return creator();
}
TEST_F(fixture, test_foo)
{
creator = []() {
std::unique_ptr<MockInterface> mock { new MockInterface() };
EXPECT_CALL(*mock, foo()).Times(1);
return mock;
};
// Will call Interface::create which will call creator()
some_function();
}

Related

Changing the underlying pointer type of a Singleton

I have a singleton class B which contains a certain method RunTimer() that I'd like to unit test which is a wrapper around an external utility. For unit test, I want to exclude the testing of the timer and rely on other parameters (not shown here)
Fake is what I'd use in unit test which will contain additional ways for the sake of testing.
Since there's only ever a single instance of a Singleton, does the idea of switching out the std::unique_ptr<ITimer> _ptr for Fake in unit test make sense for the sake of testing?
class ITimer
{
public:
virtual void foo() = 0;
virtual ~Base() = default;
};
class Real : public ITimer
{
public:
void foo() override {}
};
// For unit test
class Fake : public ITimer
{
public:
void foo() override {}
};
class B
{
std::unique_ptr<ITimer> _ptr;
// default ctor creates a Real
B() : B(std::make_unique<Real>())
{
}
B(std::unique_ptr<ITimer> ptr) : _ptr(std::move(ptr))
{
}
public:
static B& get()
{
static B b;
return b;
}
void RunTimer()
{
Timer::Run(); // external utility
}
void change(std::unique_ptr<Base> ptr)
{
_ptr = std::move(ptr);
}
};
int main()
{
B::get(); // use Real in actual code
// use Fake - for testing (eventually to be in TEST_F())
auto mk = std::make_unique<Fake>();
B::get().change(std::move(mk));
// do testing on B::_ptr
}

How to use MOCK_METHOD on a virtual function from a different class inside a Mock?

I am trying to use EXPECT_CALL to set the return value of the function that resides in a different class than what the mock class inherits from.
In the following snippet, I was wondering if there's a way to use EXPECT_CALL on someFunction() that's a public function of Bar inside a unit test through bar object of UnitTest class but it seems to error out.
One thing I know is I would need to use MOCK_METHOD for someFunction to override it to expect EXPECT_CALL but not sure how could I do inside the Mock class?
// Bar.hpp
class Bar
{
public:
virtual bool someFunction();
};
// Foo.hpp
namespace sw::foo_state
{
class Foo
{
Bar _bar;
public:
Foo(Bar&& bar) : _bar(std::move(bar)) {}
void TestFunction()
{
_bar.someFunction();
}
};
};
// MockClass.hpp
namespace sw
{
class Mock : public foo_state::Foo
{
Mock(Bar&& bar) : Foo(std::move(bar)) {}
};
};
// UnitTest.cpp
using namespace sw::foo_state;
class UnitTest
{
public:
Bar bar;
auto ptr = std::make_unique<Mock>(std::move(bar));
};
TEST_F(UnitTest, Test)
{
EXPECT_CALL(bar, someFunction()).WillOnce(Return(true)); // error: ‘class sw::foo_state::Bar’ has no member named ‘gmock_someFunction’; did you mean ‘someFunction’?
ptr->TestFunction();
}
EDIT:
You only need to change your class Foo constructor to accept a pointer or a reference to take advantage of class Bar polymorphism:
class Bar
{
public:
virtual bool someFunction()
{
return true;
}
};
class Foo
{
public:
Foo(Bar& bar): _bar{ bar} {}
void TestFunction()
{
std::cout << _bar.someFunction() << std::endl;
}
private:
Bar& _bar; // can also be std::unique_ptr<Bar> if you prefer to own the object
};
struct MockBar : public Bar
{
MOCK_METHOD0(someFunction, bool());
};
using testing::Return;
TEST(xxx, yyy)
{
MockBar mBar;
// ON_CALL(mBar, someFunction()).WillByDefault(Return(false)); // if you don't want to force expectation
EXPECT_CALL(mBar, someFunction()).WillOnce(Return(false));
Foo foo(mBar);
foo.TestFunction();
}

capturing pointer inside boost::spawn

I have base class A which has factory method to create instances of derived classes B and C. B and C has start() overridden. There is do_work() which calls getInstance() and then calls start(). Now labmda inside spawn() does not store the instance of captures this pointer. So there is a scope problem. If I pass instance(boost::shared_ptr) to start explicitly and then capture it in lambda, then it works. How do I avoid passing instance to start()?
class B : public A {
public:
void start(){
boost::spawn(io_service, [this](boost::asio::yield_context yield)
{
// work
});
}
}
class C: public A {
public:
void start(){
boost::spawn(io_service, [this](boost::asio::yield_context yield)
{
// work
});
}
}
do_work() {
auto object = A::getInstance(); // this returns boost::shared_ptr and it does not store that instance
object->start();
}
class A {
public:
virtual void start () =0;
static boost::shared_ptr<A> getInstance() {
return boost::shared_ptr<A>(new B());
}
}
You should use enable_shared_from_this:
Live On Coliru
#define BOOST_COROUTINES_NO_DEPRECATION_WARNING
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
boost::asio::io_service io_service;
class A : public boost::enable_shared_from_this<A> {
public:
virtual void start() = 0;
static boost::shared_ptr<A> getInstance();
};
class B : public A {
public:
void start() {
auto self = shared_from_this();
boost::asio::spawn(io_service, [self](boost::asio::yield_context /*yield*/) {
// work
});
}
};
class C : public A {
public:
void start() {
auto self = shared_from_this();
boost::asio::spawn(io_service, [self](boost::asio::yield_context /*yield*/) {
// work
});
}
};
/*static*/ boost::shared_ptr<A> A::getInstance() { return boost::shared_ptr<A>(new B()); }
void do_work() {
auto object = A::getInstance(); // this returns boost::shared_ptr and it does not store that instance
object->start();
}
int main() {
}
Honestly, I don't know why the compiler let this pass. The start function doesn't exist in the A world.
Classes B and C haven't overridden anything unless there is a virtual function in their base class to override. Add a pure virtual start to class A, then decorate the B and C start functions with virtual. Then will those two classes have overridden something. I suspect that will result in the behavior you're expecting.
class A {
public:
static boost::shared_ptr<A> getInstance() {
return boost::shared_ptr<A>(new B());
}
virtual void start()=0;
};
class B : public A {
public:
virtual void start() {
// stuff specific to class B
}
};
class C : public A {
public:
virtual void start() {
// stuff specific to class C
}
};

How to use shared_ptr to supply mock object from outside?

I want to test an app Thud, which will use a resource Foo. It will not own a concrete object but will have a pointer to a abstract resource interface (IFoo here). In production I will supply it with the actual resource implementation (FooImpl) whereas for unit test I want to send a pointer to a mock resource. How should I do this ? I've tried to write the least code just to get to point,
class IFoo
{
public:
virtual bool Foo(bool) = 0;
};
class FooImpl : public IFoo
{
public:
bool Foo(bool b) override
{
return b;
}
};
class FooMock : public IFoo
{
public:
MOCK_METHOD1(Foo, bool(bool));
};
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
//foo.reset(&mock); //line#1
foo = &mock; //line#2
}
FooMock mock;
//std::shared_ptr<IFoo> foo; //line#3
IFoo* foo; //line#4
};
class Thud
{
//std::shared_ptr<IFoo> fooPtr; //line#5
IFoo* fooPtr; //line#6
public:
/*Thud(std::shared_ptr<IFoo> fooPtr_) : fooPtr{ fooPtr_ }
{}*/ //line#7
Thud(IFoo* fooPtr_) : fooPtr{ fooPtr_ }
{} //line#8
bool thud1(bool b)
{
return fooPtr->Foo(b);
}
};
TEST_F(ThudTest, fooFalse)
{
bool b = false;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(false));;
Thud thud(foo);
EXPECT_FALSE(thud.thud1(b));
}
TEST_F(ThudTest, fooTrue)
{
bool b = true;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(true));;
Thud thud(foo);
EXPECT_TRUE(thud.thud1(b));
}
int main(int argc, char** argv) {
// The following line must be executed to initialize Google Mock
// (and Google Test) before running the tests.
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
So for completion I've has an overloaded constructor that takes not arguement but will do the following,
Thud():fooPtr {std::make_shared<FooImpl>()}
{}
to get the real implementation in production.
But now how do I make the pointer point to the mock object. As you can see, I'm using GMock framework here. How to achieve this ?
If I comment out line #2,4,6 & 8 which uses a plain old raw pointer and uncomment and use line #1,3,5 & 7 (using the shared_ptr in question here) instead, it crashes with heap corruption after the first test case.
It works perfectly with this raw pointer.
You cannot do foo.reset(&mock), since then mock has two owners: its automatic storage duration, plus the shared pointer foo. Memory corruption FTW.
You should simply allocate the FooMock dynamically and pass it in when creating the Thud instance being tested:
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
foo = std::make_shared<FooMock>();
}
std::shared_ptr<FooMock> foo;
};
You won't even need the mock member any more. Note that I've changed the type of foo to know about FooMock, so that you can access that type. If you really want foo to remain mock-unaware, do it like this:
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
mock = std::make_shared<FooMock>();
foo = mock;
}
std::shared_ptr<FooMock> mock;
std::shared_ptr<IFoo> foo;
};
However, this should not be necessary, since std::shared_ptr<FooMock> is implicitly convertible to std::shared_ptr<IFoo>.
With:
class Thud
{
std::shared_ptr<IFoo> fooPtr;
public:
Thud(std::shared_ptr<IFoo> fooPtr_) : fooPtr{ fooPtr_ }
{}
bool thud1(bool b)
{
return fooPtr->Foo(b);
}
};
Your tests can become (I remove the Feature):
TEST(ThudTest, fooFalse)
{
auto mock = std::make_shared<FooMock>()
bool b = false;
EXPECT_CALL(*mock, Foo(b)).Times(1).WillOnce(Return(false));;
Thud thud(mock);
EXPECT_FALSE(thud.thud1(b));
}
TEST(ThudTest, fooTrue)
{
auto mock = std::make_shared<FooMock>()
bool b = true;
EXPECT_CALL(*mock, Foo(b)).Times(1).WillOnce(Return(true));;
Thud thud(mock);
EXPECT_TRUE(thud.thud1(b));
}
In my solution a needed to use shared_ptr<IFoo> to add it to collection in other tested class and I figured out to use a referecne ;). Then I tried with NiceMock<IFoo> and StrictMock<IFoo> also and it worked.
using namespace testing;
using namespace std;
class ThudTest : public Test {
public:
shared_ptr<FooMock> fooPtr_ = make_shared<FooMock>();
// shared_ptr<StrictMock<FooMock>> fooPtr_ = make_shared<StrictMock<FooMock>>();
FooMock& mock = *fooPtr_;
// StrictMock<FooMock>& mock= *fooPtr_;
bool thud1(bool b) {
return fooPtr_->Foo(b);
}
};
And tests can be writen without *:
TEST_F(ThudTest, fooFalse) {
bool b = false;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(false));
EXPECT_FALSE(thud1(b));
}
TEST_F(ThudTest, fooTrue) {
bool b = true;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(true));
EXPECT_TRUE(thud1(b));
}

gmock: Why isn't EXPECT_CALL detecting the function call in my test?

The text "callback called" from Callback() prints to console, but gmock fails the test saying that no callback happened. What am I doing wrong?
class MyClass
{
public:
MyClass() { };
virtual ~MyClass() { };
void Callback() { printf("callback called\n"); };
};
class MyClassMock : public MyClass
{
public:
MOCK_METHOD0(Callback, void());
};
class Caller
{
public:
Caller(MyClass *myClass) { m_myClass = *myClass; };
void Call() { m_myClass.Callback(); };
private:
MyClass m_myClass;
};
TEST(BasicTest, Positive)
{
MyClassMock mock;
EXPECT_CALL(mock, Callback()).Times(1);
Caller caller(&mock);
caller.Call();
}
Your
void Callback();
method is not declared virtual. So you can't mock it that way with a simple derived mock class.
To cite from the google-mock documentation
Google Mock can mock non-virtual functions to be used in what we call hi-perf dependency injection.
In this case, instead of sharing a common base class with the real class, your mock class will be unrelated to the real class, but contain methods with the same signatures.
The consequence is you have to realize this with a template. There's a concise example given at the documentation section linked from above.
Trying to "translate" their sample to your case, it should look like
class MyClass {
public:
MyClass() { };
virtual ~MyClass() { };
void Callback() { printf("callback called\n"); };
};
class MyClassMock {
public:
MOCK_METHOD0(Callback, void());
};
template<class T>
class Caller {
public:
Caller(T& myClass) : m_myClass(myClass) {}
void Call() { m_myClass.Callback(); }
private:
T& m_myClass;
};
TEST(BasicTest, Positive) {
MyClassMock mock;
EXPECT_CALL(mock, Callback()).Times(1);
Caller<MyClassMock> caller(mock);
caller.Call();
}