How to use mocks with a test fixture in GMock? - c++

I have a test fixture in my tests so I don't have to instantiate objects of my class repeatedly, but I'm not sure how to use mocks with it. To put it simply, this is how the class is defined:
class Class1 {
public:
Class1(std::shared_ptr<Class2> class_two);
void doThisThing() { doThatThing(); }
}
class Class2 {
public:
Class2(Class3* class3_ptr);
int doThatThing();
}
(class 1 is constructed using a shared pointer to class 2. Class 2 is constructed with a pointer to class 3. Class 1 calls on a function "doThisThing" which calls Class 2's function doThatThing.)
I need to create a mock for doThatThing() (and the rest of Class2's functions), but can't figure out how to pass the mock object to Class 1. Here is what I have so far in my testing code:
class TestClass1 : public ::testing::Test {
TestClass1(){
//Construct instance of Class1 and store as member variable
std::shared_ptr<Class3> class_three = std::make_shared<Class3>();
std::shared_ptr<Class2> class_two = std::make_shared<Class2>((Class3*)class_three.get());
class_one = new Class1(class_two);
};
Class1* class_one;
}
MockClass2 : public Class2 {
MOCK_METHOD0(doThatThing, int());
}
TEST_F(TestClass1, doThatThingTest){
MockClass2 mockObj;
**THIS IS WHERE I'M STUCK. How do I get that mockObj into my TestClass1 Fixture? As of now, it is calling the actual function, not the mock***
class_one->doThatThing();
EXPECT_CALL(mockObj, doThatThing());
}
I had to abstract and simplify the actual code, so I hope the above makes sense.

Assuming that your MockClass2 works, you should try something like the following:
Here you should override the functions SetUp that is called right before every call of a test function to prepare your test data. And override TearDown that is called after every call of a test function to clean up test data.
struct TestClass1 : public ::testing::Test
{
void SetUp() override
{
class_two_mock = std::make_shared<MockClass2>();
class_one = std::make_unique<Class1>(class_two_mock);
}
void TearDown() override
{
class_one.reset();
class_two_mock.reset();
}
std::shared_ptr<MockClass2> class_two_mock
std::unique_ptr<Class1> class_one;
};
In the test function you must declare your expectations before something is executed.
TEST_F(TestClass1, doThatThingTest)
{
EXPECT_CALL(*class_two_mock, doThatThing());
class_one->doThatThing();
}
You may need an interface for Class2. The code here is not tested.

Related

gmock: force mocking out of a class method without defining and referencing a mock class?

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

Passing a mock as a unique_ptr when base class does not have a virtual destructor

I have a library class that I need to mock in one of my tests, and the object that accepts it takes a unique_ptr to one. After reading this answer, I assumed I could just do something like this.
class LibraryClassMock : public LibraryClass {
public:
MOCK_METHOD0(do, void());
};
TEST(ProxyServiceTest, RequestMade) {
auto mock = std::make_unique<LibraryClassMock>();
auto mockPtr = mock.get();
// Setup mock
EXPECT_CALL(*mockPtr, do()).Times(1);
// Signature of constructor is MySerivce(std::unique_ptr<LibraryClass>)
MyService service{std::move(mock)};
proxyService.runCommand("cmd");
}
Unfortunately, LibraryClass does not have a virtual destructor (nor can I add one), and because MyService holds a pointer of the form unique_ptr<LibraryClass>, this scope ending causes a leak (as the mock's destructor is not called). Without reworking Service to accept a shared_ptr, is there a way to work around this? In my application, service should be controlling the lifetime of the object passed in, but I need to mock it for my test.
You could introduce some stub classes and wrapper that don't need a destructor. Then you put the g-mock methods on the stub class.
class TestLibraryClass {
public:
virtual void do() {};
}
class LibraryClassMock : public TestLibraryClass {
public:
MOCK_METHOD0(do, void());
};
class LibraryClassMockWrapper : public LibraryClass {
public:
LibraryClassMock* pMock;
void do() override {
pMock->do();
}
};
TEST(ProxyServiceTest, RequestMade) {
auto mock = new LibraryClassMock();
// Setup mock
EXPECT_CALL(mock, do()).Times(1);
// setup unique_ptr
std::unique_ptr<LibraryClass> upWrapper(new LibraryClassMockWrapper()); // upWrapper owns mockWrapper lifetime, but not mock
upWrapper->pMock = mock;
// Signature of constructor is MySerivce(std::unique_ptr<LibraryClass>)
MyService service{std::move(upWrapper)};
proxyService.runCommand("cmd");
delete mock;
}

Unit testing classes that use dagger 2 to create objects

Let's say I have a dagger 2 module as follows,
#Module
interface Creator {
MyClass create();
}
and I am using it to create an instance of MyClass
class Instantiator {
void doSomething(){
MyClass clazz = DaggerCreator.create().create();
// do things with clazz
}
}
It seems to me that I cannot effectively test the doSomething method in Instantiator because I cannot provide a mock for MyClass.
Am I wrong? If not are we supposed to use Dagger instantiation sparingly?
You are correct in saying that it is hard to test use of a Component injector, since this is a static method. But harder than what? Here is the same method using instantiation:
class Instantiator {
void doSomething(){
MyClass clazz = new MyClass();
// do things with clazz
}
}
still hard to test, right?
The point is to use as few Component (injectors) as possible and to pass in dependencies in the constructor for your objects. Dagger 2 makes resolving the dependencies in the constructor easy. This thereby makes testing easy since you can pass in mock object in a constructor.
Let's refactor the code you wrote to be testable. Assume that MyClass contains a single method, fireLazers() that you want to test is being invoked inside Instantiator's doSomething() method:
public class DoerOfSomething {
private final MyClass myClass;
#Inject
public DoerOfSomething(MyClass myClazz) {
this.myClass = myClazz;
}
public void doSomething() {
myClass.fireLazers();
}
}
Now you can write a test like this using a mock object:
public void DoerOfSomethingTest {
//mocks
MyClass mockMyClass;
//system under test
DoerOfSomething doerOfSomething;
#Before
public void setUp() {
mockMyClass = Mockito.mock(MyClass.class);
}
#Test
public void whenDoSomething_thenInteractsWithMyClass() {
//arrange
doerOfSomething = new DoerOfSomething(mockMyClass);
//act
doerOfSomething.doSomething();
//assert
verify(mockMyClass).fireLazers();
}
}
Of course, you will now need to inject DoerOfSomething into the top level class where you are injecting, but now you can be certain that the object you are injecting is functioning as expected because it is testable. Your code for using Dagger looks a bit unusual but I'll use your idioms for the sake of parity between the question and the answer.
class Instantiator {
private final DoerOfSomething doerOfSomething;
Instantiator() {
doerOfSomething = DaggerCreator.create().create();
}
void doSomething() {
doerOfSomething.doSomething();
}
}

Google Mock Help Required,

I have 2 classes.
class SomeClass
{
public:
int SomeFunction()
{
return 5;
}
};
class AnotherClass
{
public:
int AnotherFunction(SomeClass obj)
{
return obj.SomeFunction();
}
};
I have made a mock class for SomeClass.
class MockSomeClass : public SomeClass
{
public:
MOCK_METHOD0(SomeFunction, int());
};
Now I want in unit test that when i call AnotherClass.AnotherFunction i get result of my own choice. AnotherFunction uses function of SomeClass.SomeFunction(). I have mocked SomeClass. And I have set that when function of mocked object calls it returs 10. But when i run unit test it returns 5 (origional function). What should i do. Below is the unit test which i have written.
[TestMethod]
void TestMethod1()
{
MockSomeClass mock;
int expected = 10;
ON_CALL(mock, SomeFunction()).WillByDefault(Return(expected));
AnotherClass realClass;
int actual = realClass.AnotherFunction(mock);
Assert::AreEqual(expected, actual);
};
I am using visual studio 2008 and gmock 1.6.0. What is wrong I am doing. on realClass.AnotherFunction i want mocked output from mock.SomeFunction().
The problem is that SomeClass::SomeFunction(...) isn't virtual, make it virtual and it will work.
Update:
There is one more fundamental error that causes it to fail, that is the method signature of
int AnotherFunction(SomeClass obj)
which creates a new SomeClass object instance which will in it's turn cause the normal SomeFunction to be called, you should instead pass a reference to the mocked class as argument.
int AnotherFunction(SomeClass* obj)
and invoke it using
int actual = realClass.AnotherFunction(&mock);

How to create Mock for the abstract base class using MOQ framework?

I want to write unit tests for MyClass but its base class is an abstract class.
public class MyClass : AbstractBaseClass
{
}
I want to Mock the AbstractBase class, so that I can skip some of the logic in its constructor when I create the MyClass instance I want to test. Is there anyway I can do this?
//Unit Test
var test = new Mock<IInterface>();
var derivedclass = new DerivedClass(test.Object);
test.Setup(d=>d.MyMethod(It.IsAny<string>()).returns(2);
derivedclass.MyMethod("hello");
// Derived Class
class DerivedClass : AbstractClass{
//constuctor
public DerivedClass(IInterface interface){
_interface = interface;
}
public MyMethod(string str){
return 2;
}
}
//Abstract Class
public abstract class AbstractClass
{
// This method gets called when i create the instance of the derived class in my unit
test..
protected AbstractedClass() : this(new SomeOtherClass()){
DoSomethingElse(); /// I want to skip this method or mock it.
}
}
By inheriting from the base class you are extending it. It is more about getting your code into a testable state rather than having Moq work for you.
You can either use composition instead of a base class and then use dependency injection (via an interface) that you can mock.
Or if you have to inherit then extract the logic that you don't want to run into another class that you inject again via dependency injection.
Or have that logic that you don't want to run be part of a virtual method that you can mock. (like #Ohad Horesh's answer:)
public virtual void DoSomethingElse();
mock.Setup(abs => abs.Foo()); //here the mocked method will be called
// rather than the real one
If these options are not viable then you will either have to test that functionality through the derived class or use another mocking framework such as TypeMock Isolator, Moles or JustMock.
Yes this is a pretty basic scenario in Moq.
Assuming your abstract class looks like this:
public class MyClass : AbstractBaseClass
{
public override int Foo()
{
return 1;
}
}
You can write the test below:
[Test]
public void MoqTest()
{
var mock = new Moq.Mock<AbstractBaseClass>();
// set the behavior of mocked methods
mock.Setup(abs => abs.Foo()).Returns(5);
// getting an instance of the class
var abstractBaseClass = mock.Object;
// Asseting it actually works :)
Assert.AreEqual(5, abstractBaseClass.Foo());
}