Search code examples
c++unit-testingmockinggooglemock

GMOCK Uninteresting Function call for any test that isn't the first test on a shared pointer mock object


I'm running into an issue where I am calling the same function call to a GMOCK object in multiple different tests. The expect call is always the same. However, only the first test will match the expect call with the real call. Subsequent tests that make the same expect call will instead fail out with the following message:

Unexpected mock function call - returning default value. Function Call: getNewTempAccountSlot(@0xaddrs 4-byte object < XX-XX-XX-XX >) The mock function has no default action set, and its return type has no default default value set.

So, here's a code example of whats going on, here's how I setup my fixture.

struct fixture
{
    Payment *MOCK_payment;

    NiceMock<GMOCK_AccountDatabase_I*> *MOCK_accountDatabase = new NiceMock<GMOCK_AccountDatabase_I()>;
    std::shared_ptr<GMOCK_AccountDatabase_I> MOCK_accountDatabaseSharedPtr = std::shared_ptr<NiceMock<GMOCK_AccountDatabase_I>>(MOCK_accountDatabase);

    std::shared_ptr<GMOCK_ClientAccount_I> MOCK_clientAccount;

    TransactionProcessor testTransactionProcessor;

   Fixture()
   : testTransactionProcessor(MOCK_accountDatabaseSharedPtr),
     MOCK_clientAccount(std::make_shared<GMOCK_ClientAccount_I>())
   {
       MOCK_payment = new Payment();
   }
   ~Fixture()
   {
       delete MOCK_payment;
       MOCK_payment = 0;

       Mock::VerifyAndClearExpectations(MOCK_clientAccount.get());
   }

   setPaymentData(ClientAccountType acc_type)
   {
       MOCK_payment->paymentData.account_type = acc_type;
   }
}

And here is how I evaluate my tests

TEST(TransactionProcessorTest, New_Automatic_Payment)
{
    Fixture f;
    f.setPaymentData(AccountTypes::ACC_DEFAULT);

    InSequence s1;

    EXPECT_CALL(*f.MOCK_accountDatabase, getNewTempAccountSlot(AccountTypes::ACC_DEFAULT)).WillOnce(Return(f.MOCK_clientAccount);

    f.testTransactionProcessor.processPayment(*f.payment);
}



TEST(TransactionProcessorTest, New_Manual_Payment)
{
    Fixture f;
    f.setPaymentData(AccountTypes::ACC_DEFAULT);

    InSequence s1;

    EXPECT_CALL(*f.MOCK_accountDatabase, getNewTempAccountSlot(AccountTypes::ACC_DEFAULT)).WillOnce(Return(f.MOCK_clientAccount);

    f.testTransactionProcessor.processPayment(*f.payment);
}

Finally, here is the source code:

void AccountDatabase::processPayment(AccountTypes type)
{
    std::shared_ptr<ClientAccount_I> temp_client_account = nullptr;
    temp_client_account = AccountDatabasePtr->getNewTempAccountSlot(type);

    if(temp_client_account != nullptr){
    ...
    }
}

I'm really quite confused because it recognizes what object is being passed into it the first time. I can actually reorder the tests and it will always pass on the first test and fail for the rest. Can anyone offer any insight as to how I can circumvent this issue? Thank you in advance for your patience.


Solution

  • Alright, I'm answering my own question because I just figured it out and if anyone else can learn from it then I hope they can take advantage of my folly.

    Basically, I ASSUMED that my f.setPaymentData(AccountType type) was setting the data for the account type enum. I did this because the first test passes! (That and because the real data has a lot more fields and I over looked it). But as it turns out, I wasn't! I'm not sure why the first google mock expect call passed but after I set the data, the rest of them started to pass too. I hope this helps.

    (I'm also not sure why it was down voted, if I'm doing something wrong, I will always appreciate insight as to how I can do better, cheers)