28

I have a mock object setup that looks like this:

MyObject obj;
EXPECT_CALL(obj, myFunction(_))
.WillOnce(Return(1))
.WillOnce(Return(1))
.WillOnce(Return(1))
.WillRepeatedly(Return(-1));

Is there a way to not have to repeat .WillOnce(Return(1)) three times?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
UXkQEZ7
  • 1,114
  • 1
  • 14
  • 24

3 Answers3

45
using testing::InSequence;

MyObject obj;

{
  InSequence s;
  EXPECT_CALL(obj, myFunction(_))
      .Times(3)
      .WillRepeatedly(Return(1));
  EXPECT_CALL(obj, myFunction(_))
      .WillRepeatedly(Return(-1));
}
VladLosev
  • 7,296
  • 2
  • 35
  • 46
  • Ah! Didn't know these can be combined this way. That looks much easier than my proposal :-) ... – πάντα ῥεῖ Aug 08 '13 at 17:17
  • or `EXPECT_CALL(...).WillRepeatedly(Return(-1)); EXPECT_CALL(...).Times(3).WillRepeatedly(Return(1).RetiresOnSaturation();` which looks a little overkill here, but there are other cases where it could be helpful. – dwanderson Oct 30 '15 at 19:09
  • Currently this function executes only 2 times for my code – hariudkmr Mar 18 '20 at 04:28
4

For completeness' sake, there's another standard/simple option, though the accepted answer seems clearer in this case.

EXPECT_CALL(obj, myFunction(_)).WillRepeatedly(Return(-1));
EXPECT_CALL(obj, myFunction(_)).Times(3).WillRepeatedly(Return(1)).RetiresOnSaturation();

This can be useful if you know what you want your last/default response to be (-1), but want to muck with the number of times its called before then.

dwanderson
  • 2,775
  • 2
  • 25
  • 40
1

I'm afraid there's no other way to configure this behavior. Can't find an obvious way in the documentation at least.

You'll might get off this problem introducing an appropriate user defined matcher though, that keeps track of a calling count and threshold you can provide from your testcases via template parameters (don't actually know how to induce the ResultType automatically :-( ):

using ::testing::MakeMatcher;
using ::testing::Matcher;
using ::testing::MatcherInterface;
using ::testing::MatchResultListener;

template
    < unsigned int CallThreshold
    , typename ResultType
    , ResultType LowerRetValue
    , ResultType HigherRetValue
    >
class MyCountingReturnMatcher 
: public MatcherInterface<ResultType>
{
public:
    MyCountingReturnMatcher()
    : callCount(0)
    {
    }

    virtual bool MatchAndExplain
        ( ResultType n
        , MatchResultListener* listener
        ) const 
    {
        ++callCount;
        if(callCount <= CallThreshold)
        {
            return n == LowerRetValue;
        }

        return n == HigherRetValue;
    }

    virtual void DescribeTo(::std::ostream* os) const 
    {
        if(callCount <= CallThreshold)
        {
            *os << "returned " << LowerRetValue;
        }
        else
        {
            *os << "returned " << HigherRetValue;
        }
    }

    virtual void DescribeNegationTo(::std::ostream* os) const 
    {
        *os << " didn't return expected value ";
        if(callCount <= CallThreshold)
        {
            *os << "didn't return expected " << LowerRetValue 
                << " at call #" << callCount;
        }
        else
        {
            *os << "didn't return expected " << HigherRetValue 
                << " at call #" << callCount;
        }
    }

private:
    unsigned int callCount;
};

template
    < unsigned int CallThreshold
    , typename ResultType
    , ResultType LowerRetValue
    , ResultType HigherRetValue
    >
inline Matcher<ResultType> MyCountingReturnMatcher() 
{
    return MakeMatcher
               ( new MyCountingReturnMatcher
                    < ResultType
                    , CallThreshold 
                    , ResultType
                    , LowerRetValue
                    , HigherRetValue
                    >()
               );
}

Use then to expect a certainly counted call result:

EXPECT_CALL(blah,method)
   .WillRepeatedly(MyCountingReturnMatcher<1000,int,1,-1>()) // Checks that method
                                                             // returns 1000 times 1
                                                             // but -1 on subsequent 
                                                             // calls.

NOTE
I didn't check this code to be working as intended, but it should guide you into the right direction.

DerKasper
  • 167
  • 2
  • 11
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190