سؤال

I have a class that takes a boolean as a reference parameter and returns an integer:

class Foo
{
  public:
    Bar my_bar;
    virtual int myMethod(bool &my_boolean) = 0;
}

/*...*/

int Foo::myMethod(bool &my_boolean){
  if (my_bar == NULL){
    my_boolean = false;
    return -1;
  }
  else{
    my_boolean = true;
    return 0;
  }

}

And I created a mock for this class:

class MockFoo : public Foo
{
   MOCK_METHOD1(myMethod,int(bool &my_boolean));
}

I'm having problems on how to set the expectations for this kind of function,because I need to set the return value and the reference parameter to specific values to properly create my unit tests.How can I deal with this kind of function with gmock?I tried following what I thought was the solution on the documentation:

using ::testing::SetArgPointee;

class MockMutator : public Mutator {
  public:
  MOCK_METHOD2(Mutate, void(bool mutate, int* value));
  ...
};
  ...

MockMutator mutator;
EXPECT_CALL(mutator, Mutate(true, _))
  .WillOnce(SetArgPointee<1>(5));

But either I didn't understood the example or it wasn't applicable for this case.Has anyone dealt whith this kind of situation before?

Thanks in advance.

هل كانت مفيدة؟

المحلول

Your question is hard to get! The samples from google mocks 'cook book' are so as well.

Do you want to reuse the implementation for Foo::myMethod() with you mock class, or do you just want to mock the side effects (return value and changed by ref parameters) for specific call situations?

A mock class is usually meant to replace / simulate your Foo class, not to inherit it directly or it's behavior. Don't know if the way you define this 'default' behavior for a pure method will work, but doubt that. You might simply omit the = 0 then. The better approach would be to separate out a real interface declaration like:

struct IFoo
{
    virtual int myMethod(bool &my_boolean) = 0;
    virtual ~IFoo() {}
};

class Foo : public IFoo
{
    // ...
};

class MockFoo : public IFoo
{
   MOCK_METHOD1(myMethod,int(bool &my_boolean));
};

If you have the latter case, you should get off with testing::Return(value) and testing::SetArgReferee<N>(value) (found that in the very useful 'Cheat Sheet').

Your expectation call should look like this then:

MockFoo foo;

// Expect call to myMethod() return -1 and set the by ref argument to true
EXPECT_CALL(foo, myMethod(_))
  .WillOnce(DoAll(SetArgReferee<0>(true),Return(-1)));

// Expect call to myMethod() return 0 and set the by ref argument to false
EXPECT_CALL(foo, myMethod(_))
  .WillOnce(DoAll(SetArgReferee<0>(false),Return(0)));

If you really want to reuse your original classes logic for myMethod() have a look at 'Delegating calls to a parent class', resp. 'Delegating Calls to a Real Object'

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top