Как вернуть определенное значение каждый раз при последовательном вызове с помощью Gmock - PullRequest
1 голос
/ 29 апреля 2019

В коде тестового фрагмента Google Mock есть EXPECT_CALL, который возвращает True и ссылку на аргумент 200 раз.

Как разрешить тесту возвращать True только каждый раз.Например, возвращайте True каждый 10-й вызов, а в противном случае возвращайте False.

class MockHandler : public Handler
{
    public:
        MOCK_METHOD1(RxMsg, bool(Msg &msg));
}

TEST(TestDispatcher, HandlePing)
{
    auto mockedHandler = make_unique<MockHandler>();
    Msg rxMsg = { REQUEST::REQ_PING, sizeof(DefaultMsg_t), rxMsg.rx,(uint8_t*)"0"};

    EXPECT_CALL(*mockedHandler, 
        RxMsg(_)).Times(checkValue).WillRepeatedly(
            DoAll(SetArgReferee<0>(rxMsg), Return(TRUE)));

    Dispatcher dispatcher(10, mockedHandler);

    for (int i = 0; i < 199; i++)
    {
        dispatcher.RunToCompletion();
    }
}

1 Ответ

1 голос
/ 29 апреля 2019

Есть несколько подходов, которые могут работать для вас. Мне нравится решение с Invoke в качестве действия по умолчанию, потому что оно наиболее гибкое. Вы не указали mcve в своем вопросе, поэтому я написал очень простые реализации для используемых вами классов. Также вы допустили ошибку, используя unique_ptr для макета. В 99% случаев это должно быть shared_ptr, поскольку вы делите его между средой тестирования и тестируемой системой.

class Msg {};

class Handler {
public:
    virtual bool RxMsg(Msg &msg) = 0;
};

class MockHandler: public Handler
{
public:
    MOCK_METHOD1(RxMsg, bool(Msg &msg));
};

class Dispatcher {
public:
    Dispatcher(std::shared_ptr<Handler> handler): h_(handler) {}
    void run() {
        Msg m;
        std::cout << h_->RxMsg(m) << std::endl;
    }
private:
    std::shared_ptr<Handler> h_;
};

class MyFixture: public ::testing::Test {
protected:
    MyFixture(): mockCallCounter_(0) {
        mockHandler_.reset(new MockHandler);
        sut_.reset(new Dispatcher(mockHandler_));
    }
    void configureMock(int period) {
        ON_CALL(*mockHandler_, RxMsg(_)).WillByDefault(Invoke(
            [this, period](Msg &msg) {
                // you can also set the output arg here
                // msg = something;
                if ((mockCallCounter_++ % period) == 0) {
                    return true;
                }
                return false;
            }));
    }
    int mockCallCounter_;
    std::shared_ptr<MockHandler> mockHandler_;
    std::unique_ptr<Dispatcher> sut_;
};

TEST_F(MyFixture, HandlePing) {
    configureMock(10);
    for (int i = 0; i < 199; i++) {
        sut_->run();
    }
}

В начале каждого теста вы должны вызывать метод configureMock, который будет вызывать макрос ON_CALL, устанавливающий действие по умолчанию для вашего макета. Функция, переданная в Invoke, может быть любой функцией, соответствующей сигнатуре перезаписываемого метода. В этом случае это функция, которая подсчитывает, сколько раз mock уже был вызван и возвращает соответствующее значение. Вы также можете назначить некоторый конкретный объект выходному аргументу msg.

...