2

I have a huge legacy code and i am not supposed to make any changes with the existing code. Now, if i have to perform unit test on a class (say class A) that is calling a method of another class (say Class B) using a pointer of that class and its a non virtual method. How can i use google mock to mock method of Class B?

I have read of methods to do that by:
1. making it virtual;
2. using templates.

But i am not interested in changing existing legacy code.

Thanks in advance!

Gluttton
  • 5,739
  • 3
  • 31
  • 58
Anshuman
  • 21
  • 1
  • possible duplicate of [Mocking non-virtual methods in C++ without editing production code?](http://stackoverflow.com/questions/2339558/mocking-non-virtual-methods-in-c-without-editing-production-code) – Gluttton Jul 01 '14 at 19:55

1 Answers1

0

Here are the two classes you might be starting with:

Class you want to perform unit tests on:

class A {
public:
    int do_a_work(B * bPtr) {
        std::cout << "-- in a::do_a_work ---" << std::endl;
        return 1 + bPtr->do_b_work();
    }
};

Class you cannot modify:

// Class that we are *NOT* going to modify
class B {
public:
    int do_b_work() {
        std::cout << "-- in b::do_b_work ---" << std::endl;
        return 2;
    }
};

Your production (non-test) code.

A a;
B b; 
a.do_a_work(&b); // b->do_b_work will be called ... 

Solution 1. Use templates as described in the Cookbook for Mocking Nonvirtual Methods.

Update class A to use a template.

template <class B_class> 
class A {
public:
    int do_a_work(B_class * bPtr) {
        std::cout << "-- in a::do_a_work ---" << std::endl;
        return 1 + bPtr->do_b_work();
    }
};

In production code, use the real B class.

A<B> aObj;
B bObj;
std::cout << aObj.do_a_work(&bObj) << std::endl;

In test code, use a mocked B class.

// Mock class. 
// It doesn't inherit from B. 
class B_Mock {
public:
    MOCK_METHOD0(do_b_work, int());
};

Call the mock class in test code:

// Use the mocked class 
B_Mock b;
A<B_Mock> a;
a.do_a_work(); // this will use the B_Mock->do_b_work MOCK_METHOD0.

Solution 2. Wrap the class you do not want to modify in a container.

Create a new class that contains an instance of the class that you do not want to modify.

// Add B Container class 
class B_Container : public B{
private:
    B my_b;
public:
    B_Container() {}
    // Make all public functions virtual (so that we can mock them out)
    virtual int do_b_work() {  
        // Forward all work to B
        return my_b.do_b_work();
    }
    // repeat for all other public functions ...
};

Then, modify class A to use B_container instead of B.

class A {
public:
    int do_a_work(B_Container * bPtr) {
        std::cout << "-- in a::do_a_work ---" << std::endl;
        return 1 + bPtr->do_b_work();
    }
};

In production, your code looks like this:

A a;
B_Container b;  // This was just "B b;"
a.do_a_work(&b);

Now that the B_Container has a virtual function, you can mock out the calls like this:

class B_Mock : public B_Container{
public:
    MOCK_METHOD0(do_b_work, int());
};

In test code, you can do this:

B_Mock b;
A a;
a.do_a_work(); // This will call B_Mock->do_b_work, which inherits from B_Container
dannyhan12
  • 942
  • 8
  • 9