I have some C++ code as follows:
class MyClass
{
public:
MyClass(OtherClass *obj)
{
obj_ = obj;
}
void myMethod()
{
// Do something
int value = obj_->otherMethod();
// Do something else
}
private:
OtherClass *obj_;
}
I want to create a unit test to test the functionality of myMethod(). Unfortunately, OtherClass is an external library and its methods are not declared virtual (so I can't inherit the methods and stub them out in a mock). I have some experience with Mockito where I might have used a spy for this purpose. But I can't seem to find an equivalent in C++.
I'm using the googletest framework for now and the context for this question (if it helps) is in ROS, where I'm actually trying to stub out tf::TransformListener.
Question 1: Is there an alternative to spies that I might not know of and can leverage in this situation?
Question 2: If there isn't, is there a quick-and-easy way for me to restructure my code so that I can leverage a mock?
Solved by doing the following:
class IOtherMethodAdapter
{
public:
virtual int otherMethod() = 0;
}
class OtherClassOtherMethodAdapter : public IOtherMethodAdapter
{
public:
int otherMethod() { return obj_->otherMethod(); }
private:
OtherClass *obj_;
}
Now I use a pointer to IOtherMethodAdapter in MyClass instead of OtherClass and for testing I simply initialize the implementation of the interface to a stubbed/mock object. If there is another way, feel free to post that solution too.
Related
the normal pattern of gmock testing is
class MyMockClass : public MyRealClass {
/// swap out behavior of an existng method
MOCK_method(some_method .....);
}
TEST() {
MyMockClass mock;
EXPECT_CALLED(mock.some_method);
/// ******* here I have to explicitly pass in the mock obj into the system
MyConsumerClass myconsumer(mock);
myconsumer.do_something_to_trigger_mock__some_method();
}
in the above "****" line I have to explicitly pass in a mock obj into the system, i.e. compose my consumer obj with a mock obj. But now I face an existing consumer class impl, its constructor does not allow passing in the dependency objects; in fact I can probably argue that it's impossible to list all the dependency objects in the ctor of a consumer class; more importantly, my real case is that the consumer class to be tested sits several levels above the mock obj:
class MyConsumerClass {
private:
MyHelperClass helper
public:
void trigger() {
helper.trigger_again();
}
}
class MyHelperClass {
BottomClass bottom;
public:
void trigger_again() {
bottom.do_something();
}
}
class BottomClass {
public :
void do_something();
}
in this case, in our unit test, we can only instantiate the top level MyConsumerClass, and I was hoping to verify that when I call myconsumer.trigger(), I could verify that the BottomClass.do_something() is called, possibly also verifying that it's called with a specific argument. But the above class hierarchy is written so that I can not pass in a mock BottomClass obj from the top level.
in jmock or jmockit, I remember it's possible to globally wipe out the behavior of BottomClass.do_something(), without referring to a specific mock obj, i.e. "static mocking", as they are called in jmockit. is it possible to do something like that in gmock (c++)? thanks
Converting the comment to an answer:
I can think of two things:
Why don't you test your classes separately? For example, write a separate test for MyHelperClass.
If dependency injection doesn't work for you, GMock allows you to do static mocking by templatizing your classes: Convert your classes to templates, then instantiate the template with real classes for production and with mock classes for testing. See here for an example.
In your case, your code could be rewritten to something like this:
//-----------------------------------------------------------------------------
// Real classes used in production
//-----------------------------------------------------------------------------
class BottomClass {
public:
void do_something();
};
//-----------------------------------------------------------------------------
// Templatized classes used in test or production
//-----------------------------------------------------------------------------
template <class BType>
class MyHelperClass {
public:
BType bottom;
public:
void trigger_again() { bottom.do_something(); }
};
template <class BType, template <typename> class HType>
class MyConsumerClass {
public:
HType<BType> helper;
public:
void trigger() { helper.trigger_again(); }
};
//-----------------------------------------------------------------------------
// Mocked classes used in test
//-----------------------------------------------------------------------------
class MockedBottomClass {
public:
MOCK_METHOD(void, do_something, (), ());
};
TEST(BottomClassTest, Test1) {
MyConsumerClass<MockedBottomClass, MyHelperClass> mock;
EXPECT_CALL(mock.helper.bottom, do_something());
mock.trigger();
}
I had to convert some of your private members to public members for the test to work.
Live example here: https://godbolt.org/z/qc3chdxKz
I have some C++ code like this that I want to unit test:
class Example
{
private:
ExpensiveObject expensiveObject;
public:
Example() : expensiveObject() {
... constructor code
}
methodA() {
... some code
}
}
To write a unit test for methodA I need to create an instance of Example. The problem is that I don't want to initialize expensiveObject, I would want to set it to null in my unit test (I am using Google Test). Is there a way to do it?
expensiveObject cannot be assigned null. What you might want is to have a smart pointer to ExpensiveObject, and have multiple constructors or better you want to inject your dependencies.
class Example
{
private:
std::shared_ptr<ExpensiveObject> expensiveObject;
public:
Example(std::shared_ptr<ExpensiveObject> ptr) : expensiveObject(ptr) {
//... constructor code
}
methodA() {
//... some code
}
}
Now you can test it for null scenarios as well
Example ex{nullptr};
ex.methodA();
I can't think of any way to do this without slightly modifying the definition of the Example class. However, if you can tolerate to do this, there are several ways to do this: dependency injection using pointers as the other answer mentioned, or templatizing the class as shown below:
// Used for production.
class ExpensiveObject {
// Expensive stuff here
};
// Only used for testing.
class CheapObject {
// Cheap stuff here
};
// Instantiate with ExpensiveObject for production and with CheapObject for
// testing.
template <class T>
class Example {
private:
T expensiveObject;
public:
Example() : expensiveObject() {}
int methodA() { return 1; }
};
TEST(Example, Test1) {
// CheapObject is used for testing.
Example<CheapObject> example;
EXPECT_EQ(example.methodA(), 1);
}
Live example: https://godbolt.org/z/7e1rhWY4b
I'm writing tests in C++ using googleTest and want to improve them.
I try to describe what I have and what I want to achieve:
I have a class A that has an instance of class B as a member like this:
class ClassA
{
public:
//Some functions
protected:
ClassB m_b;
};
class ClassB
{
void Init(const string &sArgument);
};
In my test I create an instance of ClassA and call a function of it. In this function the function Init() of m_b will be called.
Because Init() of ClassB makes something that I don't want to have in my test I want to call an alternate implementation. My first intention was to create an interface with the function Init() that is implemented by ClassB and by a new class that I create only for the test. Unfortunately to do this I have to create a pointer of the interface and to give it to ClassA.
__interface IB
{
void Init(const string &sArgument);
};
class ClassB : public IB
{
void Init(const string &sArgument) override;
};
class ClassA
{
public:
ClassA(IB* b) : m_b(b){}
//Some functions
protected:
*IB m_b;
};
For my test I create a new class:
class ClassBForTest : public IB
{
void Init(const string &sArgument) override;
};
This is not a good solution so I tried to find another way. What I actually found is the library Isolator++ by Typemock which works quite good. I can say that for all future instances of ClassB the method Init should be replaced with another one. And the best is that I don't have to make any changes in my ClassA. I just have to create a new one:
class ClassBForTest
{
void ISOLATOR_TESTABLE Init(const string &sArgument){}
};
In my test I use this:
ClassBForTest c;
ClassB* b = FAKE_ALL<ClassB>();
WHEN_CALLED(b->Init(ANY_VAL(string))).DoMemberFunctionInstead(&c, Init);
Unfortunately this library is not for free when I want to use it on a build server. So I'm searching for an alternative. As we used gMock in our other tests I tried to realize this with gmock but it didn't work yet. I know that this is not a good statement but I don't want code from you. I only want to know if this is possible with gMock (saying that an alternate implementation should be used without having the instance of ClassB at this point).
Alternatively I ask you for other free libraries I can use.
Thanks a lot in advance,
Michaela
I have a class, say ClassA which has some public functions as well as private.
The public functions in turns class private functions.
Now my intention here is to test the private function via public function.
For Public functions, I am trying to invoke the original implementation and for private method I am trying to create a Mock function.
My Class A is like this,
class ClassA {
public:
string getName(string key) {
int value = 2;
int code = getCode(value);
if(code != 2)
cout<<"Error";
else
return "XYZ";
}
private:
int getCode(int value) {
if(value == 2)
return 2;
else
return -1;
}
};
Now I have a Mock for the ClassA like this,
class MockA : public ClassA {
public:
MOCK_METHOD1(getName,string(string key)); //Mock for public method
MOCK_METHOD1(getCode,int(int value))l //Mock for private method
}
This is my GoogleTest test case,
TEST(ClassATest, Test1)
{
MockA a;
Class a1;
EXPECT_CALL(a,getCode()).Times(1).WillOnce(Return(2));
EXPECT_CALL(a,getName()).Times(1).WillOnce(Return(Invoke(&a1,
ClassA::getName());
}
As you can see, for the private method I am using mock and for public method I am using Invoke and invoking the original implementation.
Now, when I compile this code, I get an error,
Actual function call count doesn't match EXPECT_CALL(a,getCode())....
Expected : to be called once
Actual : never called - unsatisfied and active
Now when I try to use orginal Implementation for getCode() also like,
EXPECT_CALL(a,getCode()).Times(1).WillOnce(Return(Invoke(&a1,
ClassA::getCode());
I get an compilation error saying getCode() is inaccesible which I think is expected.
By now, if you are reading this, hope you are understood my problem statement.
I have to test the private method by passing in different arguments, via the public method which I test via gtest.
I wanted to mock the private method as stated by this article in github and call the orininal production code for my public method.
Am I doing something fundamentally wrong? If so, can any of you some better methods for my use case.
I have tried FRIEND_TEST and tbh, I dont want any modifications in my production code. I will try that as a last resort.
You are trying to invoke a private method from ClassA. This is not possible except if there is a friend declaration, but yes, it's not ideal.
The problem stems from the design of your test which should call a public API and not an implementation detail.
Late answer, but I'm currently working on similar issues and saw this question.
In your example I'm not quite sure what the purpose of Invoke() is, but if all you are trying to do is verify calls to getCode() and control its return value, then you would only need to mock that one.
You would have to modify the production code to make the private function virtual, so if that's not an option then of course this wouldn't work for you. It seems like a pretty safe modification though.
class ClassA {
public:
string getName(string key) {
int value = 2;
int code = getCode(value);
if (code != 2)
return "Error";
return "XYZ";
}
private:
virtual int getCode(int value) {
if (value == 2)
return 2;
return -1;
}
};
class MockA : public ClassA {
public:
MOCK_METHOD1(getCode, int(int value));
};
TEST(ClassATest, Test1)
{
MockA mockA;
EXPECT_CALL(mockA, getCode(2)).WillOnce(Return(2));
EXPECT_EQ(mockA.getName("key"), "XYZ");
}
I have a class that is subclass of an external class over which I don't have any control. The external class depend on system resources. For example
class MyClass : public ExternalBase // This class is from external framework and framework requires it to derive from this class.
{
int doSomePrivateThing(int );
public:
virtual int DoSomething(int );
virtual ~MyClass();
}
int MyClass::doSomePrivateThing(int )
{
// do some private task
}
int MyClass::DoSomething(int n)
{
// Do MyClass Specific task
int k = doSomePrivateThing(n);
return ExternalBase::DoSomething(k); // This function depends on external system resources.
// Probably try to communicate with remote server
// or attempt access Storage or Display device etc.
}
MyClass::~MyClass()
{}
How can I break the dependency of MyClass and write unit test for MyClass::DoSomething(). Using composition in place of inheritance is not a choice as framework requires classes to be derived from this base class.
I am using C++ and GoogleTest/Mock. But any generalized solution is appreciated.
Thanks in advance.
There are two ways. I call them "a little more correct" way and "very ugly" way.
The "more correct" way:
Enclose external class functions with some additional layer than can be partial mocked.
class MyClass : public ExternalBase // This class is from external framework and framework requires it to derive from this class.
{
int doSomePrivateThing(int );
public:
virtual void BaseDoSomething(int) { return ExternalBase::DoSomething(v); }
virtual int DoSomething(int v);
virtual ~MyClass();
};
int MyClass::DoSomething(int n)
{
// Do MyClass Specific task
int k = doSomePrivateThing(n);
return BaseDoSomething(k);
}
And partial mock in UT in this way:
class TestableMyClass : public MyClass
{
public:
using MyClass::MyClass;
MOCK_METHOD1(BaseDoSomething, int(int));
};
TEST(A,A)
{
TestableMyClass objectUnderTest;
EXPECT_CALL(objectUnderTest, BaseDoSomething(112));
objectUnderTest.DoSomething(112);
}
When you need to call also the true base class method in your test - use WillOnce(Invoke...) with EXPECT_CALL.
The "very ugly" way:
Provide your own UnitTest implementation of ExternalBase and link it to your test. This "UnitTest" impolementation of ExternalBase should be based on some global Mocks objects.
ExternalBaseMock.hpp:
class ExternalBaseMock
{
public:
MOCK_METHOD1(DoSomething, int(int));
};
extern ExternalBaseMock externalBaseMock;
ExternalBaseMock.cpp:
ExternalBaseMock externalBaseMock;
int ExternalBase::DoSomething(int n)
{
return externalBaseMock.DoSomething(n);
}
Then your tests:
#include "ExternalBaseMock.hpp"
TEST(A,A)
{
MyClass objectUnderTest;
EXPECT_CALL(externalBaseMock, DoSomething(112));
objectUnderTest.DoSomething(112);
}