How to use shared_ptr to supply mock object from outside? - c++

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));
}

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();
}

Factory Pattern w/ Gmock

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();
}

How to test a class method that instantiates non mocked classes in C++?

This is my first experience in UniTesting and it's giving me headaches when developing the tests, if you could help it would be really nice.
I have in my program something like this:
class Baseclass
{
public:
Baseclass(Class2 arg) { mProperty = arg};
void doSomething();
void doSomethingElse();
private:
Class2 mProperty;
}
class Class1
{
public:
bool doClass1Stuff();
...
}
class Class2
{
public:
bool doClass2Stuff();
Class1* getClass1(){return mClass1;};
...
private:
Class1* mClass1;
}
I'm using GoogleTest and gMock to write the tests:
class MockClass1 : public Class1
{
public:
MOCK_METHOD(bool, doClass1Stuff,());
};
class MockClass2 : public Class2
{
public:
MOCK_METHOD(MockClass1*, getClass1,());
}
I can't solve the problem when testing a method of BaseClass that do something like this:
double BaseClass::methodToTest()
{
Class1* myObject = dynamic_cast<Class1*>(mProperty.getClass1());
if(myObject.doClass1Stuff())
{
//The rest of the code
}
return returnValue;
}
In the code below: when calling BaseClass::methodToTest(), mProperty.getClass1() and doClass1Stuff() are calling real methods instead of mock methods.
TEST(TestSuite1, TestName1){
MockClass1 * myMockObject1 = new MockClass1;
MockClass2 * myMockObject2 = new MockClass2;
BaseClass * testObject = new BaseClass(myMockClass2Object);
ON_CALL(myMockObject1,doClassic1Stuff()).WillByDefault(Return(true));
ON_CALL(myMockObject2, getClass1()).WillByDefault(Return(myMockObject1));
auto var = testObject.methodToTest();
ASSERT_EQ( 0.0, var);
}
How can I make BaseClass call mock methods? Should I modify the source code to test it?
I would appreciate any information you can give me. Thanks.
You have object slicing with your BaseClass usage with mock, you need something like:
class Baseclass
{
public:
Baseclass(std::unique_ptr<Class2> arg) mProperty(std::move(arg)) {}
void doSomething();
void doSomethingElse();
double methodToTest()
{
Class1* myObject = mProperty->getClass1();
if (myObject->doClass1Stuff())
{
//The rest of the code
}
return returnValue;
}
private:
std::unique_ptr<Class2> mProperty;
};
And your TEST, should be similar to:
TEST(TestSuite1, TestName1){
MockClass1 myMockObject1;
ON_CALL(myMockObject1, doClassic1Stuff()).WillByDefault(Return(true));
auto myMockObject2 = std::make_unique<MockClass2>();
ON_CALL(*myMockObject2, getClass1()).WillByDefault(Return(myMockObject1));
BaseClass testObject(std::move(myMockClass2Object));
// Note: myMockObject2 is nullptr now, as moved, you no longer can use it for ON_CALL
auto var = testObject.methodToTest();
ASSERT_EQ( 0.0, var);
}

How to mock this class

class A
{
public:
void doFirstJob()
{
// Do first Job.
}
}
class B : public A
{
public:
virtual void doSecondJob()
{
// Do Second Job.
}
}
class C
{
public:
void doSomething() {
b->doFirstJob();
b->doSecondJob();
}
private:
B* b;
}
Now I should write unit test code for class C, then I'll write a mock for class B, but the problem is how to mock the method doFirstJob().
Bluntly, I want know how to mock the non-virtual method of the parent class???
Can any one help me ??
Typemock Isolator++ supports mocking non virtual methods of a parent class (same as faking a method of the class under test).
See following example:
class A
{
public:
int doFirstJob()
{
return 0;
}
};
class B : public A
{
};
class C
{
public:
int doSomething()
{
return b->doFirstJob();
}
void setB(B* to)
{
b = to;
}
private:
B* b;
};
In the test You create a fake of B -> change the behavior of doFirstJob to return 3 -> continue with your test as you would normally write it.
TEST_CLASS(NonVirtualMethod)
{
public:
TEST_METHOD(NonVirtualMethodTestOfBaseClass)
{
B* fakeB = FAKE<B>();
WHEN_CALLED(fakeB->doFirstJob()).Return(3);
C c;
c.setB(fakeB);
int first = c.doSomething();
Assert::AreEqual(3,first);
}
}
You can find more examples here.