I try to mock a User class and its nested struct UserBuilder:
class User
{
public:
virtual int loadData(const std::string& filename);
virtual UserBuilder getUserBuilder(const std::string& functionName) const;
struct UserBuilder
{
UserBuilder(std::string functionName) : m_functionName{functionName} {};
virtual ~UserBuilder();
virtual UserBuilder& fun1();
virtual UserBuilder& fun2(int32_t num);
virtual bool callFunction();
private:
std::string m_functionName{};
};
}
This is the mock class for User:
class UserMock : public User
{
public:
MOCK_METHOD1(loadData, int(const std::string& filename));
MOCK_CONST_METHOD1(getUserBuilder, UserBuilder(const std::string& functionName));
};
Thsi is the mock class for UserBuilder:
struct UserBuilderMock : public User::UserBuilder
{
public:
UserBuilderMock(std::string functionName) : User::UserBuilder(functionName) {}
MOCK_METHOD0(fun1, UserBuilder&());
MOCK_METHOD1(fun2, UserBuilder&(int32_t num));
MOCK_METHOD0(callFunction, bool());
};
I want to test this function:
void useCase(std::unique_ptr<User> userP)
{
int status = userP->loadFile("init");
if (status == 0)
{
User::UserBuilder builder = userP->getUserlBuilder("init");
bool result = builder.fun1().fun2(1).callFunction();
return result;
}
else
{
return false;
}
}
I give the getUserBuilder("init") a mock object builderMock as its return value, like this:
auto userMock = std::make_unique<UserMock>();
ON_CALL(*userMock, loadFile("init")).WillByDefault(Return(0));
UserBuilderMock builderMock("init");
EXPECT_CALL(*userMock, getUserBuilder("init")).WillOnce(ReturnPointee(&builderMock));
EXPECT_CALL(builderMock,fun1()).Times(1);
The test log fail: fun1 never called-unsatisfied and active.
I want to use the builderMock object to call the mock method fun1,fun2 and callFunction, but it still use the real UserBuilder object
call the real fun1,fun2 and callFunction. What should I do to make it use Mock object call the Mock method?
You have to rewrite your code to make User::getUserBuilder return a pointer (possibly smart one) to UserBuilder.
With the method returning UserBuilder object
EXPECT_CALL(*userMock, getUserBuilder("init")).WillOnce(ReturnPointee(&builderMock));
getUserBuilder casts the mock to an object of its base class (slicing), losing all the the mock additions.
Related
My goal is to construct a derived classes nested class from the interface. However the nested classes don't have the same constructors. The question is how can I make an interface to create two different "sub-nested" classes.
Constraints:
Cannot use Heap
Nested Classes' Methods cannot be called before it is constructed
C++ 17
ITest::INestedTest* MakeTest(ITest* test, ITest::Config config)
{
// Can't call directly because it's not on the interface i.e. test.InitializeNestedTest ...
// Only workable situation is this:
if (condition)
{
auto myTest = static_cast<Test2::Test*>(test);
int p = 2;
return myTest->InitalizeNestedTest(config, p);
// ERROR function returning abstract class not allowed
} else {
auto myTest = static_cast<Test1::Test*>(test);
return myTest->InitalizeNestedTest(config);
// ERROR function returning abstract class not allowed
}
}
This static cast didn't return what I wanted previously because I was returning a pointer to a locally defined variable, which was pointed out in the comments. How am I able to return a class from this since it's an abstract class, do i need to cast it again or make multiple functions?
Test1::Test myTest;
auto myNestedTest = myTest.InitializeNestedTest(config);
I've thought of a few options but none of them seem right, or I'm not entirely sure how to implement them
Have an overloaded Virtual function for each type on the interface and then override them on the subclass (not sure if possible and doesn't seem like the right way to do it)
Extend the Config struct Test2 namespace so that it includes parameter p, so that they all have the same prototype and put it on the interface. (is it possible to "extend" the struct" from the interface?)
Maybe use a different type of cast, or do so in a different way?
I've included the definitions of my Interface and two subclasses for reference.
class ITest
{
//other things in ITest.hpp not relevant to question
public:
struct Config
{
int a;
bool enable;
};
class INestedTest
{
public:
virtual void Enable() const = 0;
virtual void Configure(Config const& config)
{
if(config.enable)
{
Enable();
}
}
};
};
namespace Test1
{
class Test : public ITest
{
public:
class NestedTest : public ITest::INestedTest
{
public:
NestedTest(Config const& config)
{
Configure(config);
}
void Enable() const override
{
//impl
}
}; // End NestedTest
NestedTest InitalizeNestedTest(Config const& config)
{
return NestedTest(config);
}
};
};
namespace Test2
{
class Test : public ITest
{
public:
class NestedTest : public ITest::INestedTest
{
public:
using Parameter = int;
NestedTest(ITest::Config const& config, Parameter p)
{
Configure(config);
}
void Enable() const override
{
//impl
}
}; // End NestedTest
NestedTest InitalizeNestedTest(Config const& config, NestedTest::Parameter p)
{
return NestedTest(config, p);
}
};
};
Maybe you could make the object static so it's declared in RAM at compile time (and not heap or stack).
It's a simple example to use google mocking along with fixtures. I am trying to setup up and learn google mock on Xcode and wrote following code
using ::testing::Return;
class Shape {
public:
virtual int calculateArea() = 0;
virtual std::string getShapeColor() = 0; // this interface must have been used by some other class under test
};
// Mock class for Shape
class MockShape : public Shape{
public:
MOCK_METHOD0(calculateArea, int());
MOCK_METHOD0(getShapeColor, std::string());
};
// class under test
class Show{
public:
Show() : printFlag(false), isColorValid(false) {}
void printArea(Shape *shape) {
if (shape->calculateArea() <= 0)
printFlag = false;
else
printFlag = true;
}
void printColor(Shape *shape) {
if (shape->getShapeColor().compare("black"))
isColorValid = true;
else
isColorValid = false;
}
bool printFlag;
bool isColorValid;
};
// Test fixture for class under test
class FixtureShow : public ::testing::Test{
public:
void SetUp(){}
void TearDown(){}
void SetUpTestCase(){}
void TearDownTestCase(){}
Show show; // common resources to be used in all the test cases
MockShape mockedShape;
};
TEST_F(FixtureShow, areaValid) {
EXPECT_CALL(mockedShape, calculateArea()).WillOnce(Return(5));
show.printArea(&mockedShape);
EXPECT_EQ(show.printFlag, true);
}
"TEST_F(FixtureShow, areaValid) " is giving error "Call to non static member function without an object argument". Can anyone help me why am I getting this error?
SetUpTestCase() and TearDownTestCase() are meant to be declared as static member functions. You can also delete them unless you are planning to put some code in.
I have hierarchy of classes:
class A
{
};
class B : public A
{
};
class C : public B
{
};
class D : public A
{
};
and I have some function, which performs notification:
void notify(A* sender, const NotificationType notification)
{
}
My problem is how to find out exact type of sender object. I want to find elegant way to solve this problem. I don't like to use dynamic cast for these purposes. Possible way is to define enum within class A like:
enum ClassType
{
CLASS_A,
CLASS_B,
CLASS_C,
CLASS_D
};
and defining virtual method:
virtual ClassType get_type(void) const;
But this approach has bad scalability. Another way to keep this information in NotificationType, but it has bad scalability too.
P.S. I just want to use similar code:
I want to use similar code:
void notify(A* sender, const NotificationType notification)
{
if (sender is object of A)
new GuiA();
else if (sender is object of B)
new GuiB();
else if (sender is object of C)
new GuiC();
else
new GuiD();
}
To create a matching GUI object based on the concrete type of sender, you could pass a factory to some kind of factory method in A.
class A
{
public:
virtual Agui* createGui(GuiFactory& fac) = 0;
};
class GuiFactory
{
public:
virtual Agui* forB(B&) = 0;
virtual Agui* forC(B&) = 0;
virtual Agui* forD(D&) = 0;
};
class B : public A
{
public:
Agui* createGui(GuiFactory& fac)
{
return fac.forB(*this);
}
};
void notify(A* sender, const NotificationType notification)
{
// Use A interface...
// Get the concrete GuiFactory from somewhere, and use it
auto gui = sender->createGui(win32GuiFactory);
}
If you want know type to persist your hierarchy, conside to use boost::TypeIndex (http://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html).
If you want know type to process different types in different manners, conside to use Visitor insted of type identifier or make abstract interface with virtual functions covers your needs.
EDITED
Your goal is to create different UI object for different types. You can use the following model to reach your goal:
class UIObject {...};
class UIObjectFactory {...};
class A {
public:
virtual std::unique_ptr<UIObject> Create(UIObjectFactory& factory) = 0;
};
void OnNotify(A* sender) {
auto ptr = sender->Create(GetUIFactory());
...
}
and defining virtual method:
virtual ClassType get_type(void) const;
The easiest way to achieve this and get rid of scalability issue is to implement your get_type() member function in each class A, B, C, ... this way:
typedef uintptr_t ClassType;
virtual ClassType get_type() const
{
static int dummy;
return reinterpret_cast<ClassType>(&dummy);
}
A static variable dummy will be created for each class you add this member function, so that the return value identifies uniquely the class.
I want to assign a NiceMock with the return value of a method. The NiceMock is an instance variable.
class TestFileToOsg : public testing::Test
{
public:
NiceMock<MockFileToOsg>* _mockFileToOsg;
protected:
virtual void SetUp();
};
void TestFileToOsg::SetUp()
{
_mockFileToOsg = FixtureFileToOsg::getMockFileToOsgWithValidConfig();
}
The fixture method is:
MockFileToOsg* FixtureFileToOsg::getMockFileToOsgWithValidConfig()
{
MockFileToOsg* fileToOsg = new MockFileToOsg(...);
return fileToOsg;
}
The compiler throws the following error:
error: invalid conversion from ‘MockFileToOsg*’ to ‘testing::NiceMock<MockFileToOsg>*’
How can I assign the instance variable with the return value of the fixture method?
In your testclass you should only have a pointer to your mockobject:
class TestFileToOsg : public testing::Test
{
public:
MockFileToOsg* _mockFileToOsg;
protected:
...
Your fixture should instantiate a NiceMock and return a pointer to your mockobject.
MockFileToOsg* FixtureFileToOsg::getMockFileToOsgWithValidConfig()
{
MockFileToOsg* fileToOsg = new NiceMock<MockFileToOsg>(...);
return fileToOsg;
}
The NiceMock<> derives from the mockClass.So NiceMock<> must only be used when you instantiate a MockObject.
Please, consider the following (I'm sorry for the amount of code; but this is the minimal example I could think of...):
class SomeDataThingy
{
};
struct IFileSystemProvider
{
virtual ~IFileSystemProvider() {}
//OS pure virtual methods
}
struct DirectFileSystemProvider
{
//Simply redirects the pure virtuals from IFileSystemProvider to OS functions.
}
struct SomeDataBlock
{
//Stored inside SomeDataThingy; contains specific data
SomeDataBlock(const SomeDataThingy& subject, const IFileSystemProvider& os = DirectFileSystemProvider())
{
//Calculate some data from the Operating System based upon a filename stored in SomeDataThingy.
}
};
struct IFilter
{
virtual ~IFilter() {}
virtual int Matches(const SomeDataThingy&) const = 0;
virtual void Calculate(SomeDataThingy&) const = 0;
};
class SomeFilter : public IFilter
{
int Matches(const SomeDataThingy& subject) const
{
if (!Subject.Contains<SomeDataBlock>())
return UNKNOWN;
else
return /* This filter matches */
}
void Calculate(SomeDataThingy& subject) const
{
std::auto_ptr<SomeDataBlock> data(new SomeDataBlock(subject));
subject.Install<SomeDataBlock>(data);
}
};
I would like to test SomeFilter::calculate, here. The problem is that the constructor for SomeDataBlock calls out to the filesystem. SomeDataBlock itself is tested by a mock IFileSystemProvider. However, I don't have a simple way to inject the mock into SomeFilter::Calculate; and unfortunately I cannot change the IFilter interface to allow the mock to be passed as an argument to Calculate, because there are other filters for which such a mock would not make any sense.
How can I test Calculate?
Can you modify the constructor of SomeFilter? If so, you can inject IFileSystemProvider that way.
class SomeFilter : public IFilter
{
public:
SomeFilter(const IFileSystemProvider& fs = DirectFileSystemProvider())
: fs(fs)
{
}
private:
int Matches(const SomeDataThingy& subject) const
{
if (!Subject.Contains<SomeDataBlock>())
return UNKNOWN;
else
return /* This filter matches */
}
void Calculate(SomeDataThingy& subject) const
{
std::auto_ptr<SomeDataBlock> data(new SomeDataBlock(subject, fs));
subject.Install<SomeDataBlock>(data);
}
IFileSystemProvider fs;
};
You could also create a public member on SomeFilter to allow the user to provide IFileSystemProvider, before calling Calculate, but after constructing the object.