Mock new object creation

639 views
Skip to first unread message

Kaushal Bhandankar

unread,
Jun 16, 2013, 10:15:39 AM6/16/13
to googl...@googlegroups.com
class Bar{
    Bar(struct DS * pDS) {
       // Construt Bar object
    }
    protected:
        Bar(){ }
}

class Foo{

Foo(int num){val = num}
int doSomething();

private:
   int value;
};

int Foo::doSomething()
{
    int ret = 0;
    //Code the create some data structure DS

    Bar *pBar = new Bar(struct DS * pDS);

    //Function call with pBar as argument. This function will be mocked.
    return ret;
}

===============

I want to mock the construction of new Bar object. Instead I want to create MockBar object. How to do it ?
I added a Bar() constructor in protected section, so that MockBar can be created without calling Bar constructor. Is this always a good idea ?

Regards,
Kaushal

Keith Ray

unread,
Jun 16, 2013, 12:27:41 PM6/16/13
to Kaushal Bhandankar, googl...@googlegroups.com
Try writing the code again, using the names ClassUnderTest and ClassToBeMocked; method names MethodToBeTests and MethodToBeMocked. Don't forget the use "public" and "virtual" keywords. If you still have a problem, post your code here again, ASAP.
--
 
---
You received this message because you are subscribed to the Google Groups "Google C++ Mocking Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to googlemock+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Keith Ray

unread,
Jun 16, 2013, 12:28:23 PM6/16/13
to Kaushal Bhandankar, googl...@googlegroups.com
Remember, you can only mock virtual methods.
On 2013 Jun 16, at 7:15 AM, Kaushal Bhandankar <kaush...@gmail.com> wrote:

Keith Ray

unread,
Jun 16, 2013, 12:49:56 PM6/16/13
to Kaushal Bhandankar, googl...@googlegroups.com
"MethodToBeTests" should be "MethodToBeTested."

I'm asking you to make these changes so that what you are trying to do is VERY clear to yourself and others.

Keith Ray

unread,
Jun 16, 2013, 12:50:53 PM6/16/13
to Kaushal Bhandankar, googl...@googlegroups.com
and include your actual test code in your re-stated question.

Kaushal Bhandankar

unread,
Jun 16, 2013, 1:08:59 PM6/16/13
to googl...@googlegroups.com, Kaushal Bhandankar
Updated Code:
========================================================
class ClassToBeMocked{
    public:
    ClassToBeMocked(struct DS * pDS) {
       // Construt ClassToBeMocked object
    }
    protected:
        ClassToBeMocked(){ }
}

class ClassUnderTest{
  public:
    ClassUnderTest(int num){val = num}
    int MethodToBeTests();
    virtual int MethodToBeMocked(ClassToBeMocked *ptr);

  private:
    int value;
};

int ClassUnderTest::MethodToBeTests()
{
    int ret = 0;
    //Code that create a data structure DS

    ClassToBeMocked *ptr = new ClassToBeMocked(struct DS * pDS);

    MethodToBeMocked(ptr);
    
    return ret;
}

===============================


Test Code

class MockClassUnderTest : public ClassUnderTest {
  public:
    MockClassUnderTest(int num):ClassUnderTest(num){}
    MOCK_METHOD1(MethodToBeMocked, void(struct DS * pDS));

}

class MockClassToBeMocked : public ClassToBeMocked{
   public:
     MockClassToBeMocked(){} // Calls protected constructor in ClassToBeMocked

};

MockClassUnderTest mcut(5);
mcut.MethodToBeTests(); // I want this method to create a MockClassToBeMocked object


==================================================================================
Regards,
Kaushal

Keith Ray

unread,
Jun 16, 2013, 1:23:33 PM6/16/13
to Kaushal Bhandankar, googl...@googlegroups.com
so...

1. the Method to be mocked should be in ClassToBeMocked. The reason you mock a method should be
one of the following:
(a) The ClassToBeMocked OR MethodToBeMocked does something that takes a long time, or...
(b) MethodToBeMocked doesn't return predictable values, or...
(c) ClassToBeMocked OR MethodToBeMocked relies on non-local entities: web servers, user-interface, or...
(d) ClassToBeMocked OR MethodToBeMocked requires too much setup.

You do not mock methods in the class you are testing. You mock methods in OTHER classes that the
class being tested uses.

2. the way to get the code being tested to use the mocked method, is to create an instance of
MockClassToBeMocked and get the MethodToBeTested to use that instance.

How can you get the instance of ClassUnderTest to get an instance of MockClassToBeMocked?

3. Three ways. In the test code, create an instance of MockClassToBeMocked and pass that instance into...

(a) ClassToBeMocked's constructor. Your PRODUCTION code would be calling that same constructor, but
passing an instance of ClassToBeMocked into the constructor. This means there needs to be a
member variable to hold onto that object, and the MethodToBeTested uses that member variable
to call this->MethodToBeTested(...);


(b) MethodToBeTested's argument list. Your PRODUCTION code would be calling that same method, but
passing an instance of ClassToBeMocked into MethodToBeTested's argument list.

(c) I'm not going to recommend the third way, yet. Try either (2a) or (2b).

Is this helping?

C. Keith Ray

Keith Ray

unread,
Jun 16, 2013, 1:31:32 PM6/16/13
to Kaushal Bhandankar, googl...@googlegroups.com
3. Three ways. In the test code, create an instance of MockClassToBeMocked and pass that instance into...

(a) ClassToBeMocked's constructor. Your PRODUCTION code would be calling that same constructor, but
passing an instance of ClassToBeMocked into the constructor. This means there needs to be a
member variable to hold onto that object, and the MethodToBeTested uses that member variable
to call this->anInstanceOfClassToBeMocked->MethodToBeMocked();


corrected code:

ClassUnderTest::ClassUnderTest(ClassToBeMocked* anInstanceOfClassToBeMockedIn)
{
this->anInstanceOfClassToBeMocked = anInstanceOfClassToBeMockedIn;
}

ClassUnderTest::MethodToBeTested()
{
... other code
this->anInstanceOfClassToBeMocked->MethodToBeMocked()
... other code
}

--------- or ----------

ClassUnderTest::MethodToBeTested(ClassToBeMocked* anInstanceOfClassToBeMocked)
{
...other code
anInstanceOfClassToBeMocked->MethodToBeMocked()
...other code

Kaushal Bhandankar

unread,
Jun 16, 2013, 2:00:10 PM6/16/13
to Keith Ray, googl...@googlegroups.com
Thanks for the pointers. I had thought about this.
As of now, in PRODUCTION code  the constructor ClassUnderTest::ClassUnderTest() does not accept ClassToBeMocked * as an argument. Doing this will need refactoring the code. Also, it's no wise to construct the ClassToBeMocked object so early.
The actual use case is there is a RegEx library that returns True if there is a Pattern Match. If there is a match I need to create the ClassToBeMocked object and call alarm method which takes ClassToBeMocked * as input.

Kaushal Bhandankar

unread,
Jun 18, 2013, 2:25:20 AM6/18/13
to Keith Ray, googl...@googlegroups.com
The way I fixed that is : y refactoring the code
Added a constructor ClassUnderTest::ClassUnderTest(ClassToBeMocked *)  which will be only used from Test code.
The actual constructor will create a new ClassToBeMocked object in the constructor. But not initialize it.

Where the actual ClassToBeMocked object was constructed:
Call the init() method to initialize the object. init is virtual and mocked in the MockClassToBeMocked class.

Regards,
Kaushal
Reply all
Reply to author
Forward
0 new messages