Могу ли я использовать макеты Google для проверки параметров метода, не задавая заранее ожидание?

У меня возникла ситуация, когда я хочу проверить, был ли вызван метод фиктивного объекта с параметром X, но тест получает доступ к X только после вызова фиктивного объекта, поэтому я не могу заранее установить EXPECT_CALL .

E.g.

// The class I'm testing.
class Maker
{
    void register(Listener& lis);
    Obj& make()
    {
        // make new Obj o
        // call created(o) on registered Listener  
        // return o
    }
}

class Listener
{
    virtual void created(Obj& o) = 0;
}

// The test
Listener lis;
Maker maker;
maker.register(lis);

Obj& o = maker.make();

// Check that lis was invoked using param o...how?

Могу ли я сделать это с помощью Google Mocks? Каков самый элегантный/читабельный способ сделать это с помощью Google Mocks?

Очевидно, я могу сделать свой собственный MockListener, который будет записывать параметры вызова, вместо того, чтобы использовать моки Google. Но я надеюсь, что Google mocks представит более читаемый механизм, похожий на EXPECT_CALL.


person nappyfalcon    schedule 02.10.2015    source источник


Ответы (2)


Вы можете использовать действие SaveArg<N>. чтобы сохранить значение параметра, с которым вызывается Listener::created(Obj&), чтобы вы могли сравнить его значение со значением, возвращаемым впоследствии maker.make().

Это потребует, чтобы вы предоставили оператор равенства для класса Obj, то есть bool operator==(const Obj&, const Obj&).

Тогда ваш тест может выглядеть так:

class ListenerMock : public Listener
{
public:
    MOCK_METHOD1(created, void(Obj&));
};

TEST(MakerTest, make_registersObject)
{
    ListenerMock lis;
    Maker maker;
    maker.register(lis);

    Obj createdArg;
    EXPECT_CALL(lis, created(_))
        .Times(1)
        .WillOnce(SaveArg<0>(&createdArg));

    Obj& o = maker.make();

    ASSERT_EQ(createdArg, o);
}
person Antonio Pérez    schedule 20.10.2015

Я думаю, что ответ заключается в том, что Google mocks был создан не для этого.

Похоже, что он создан для тестирования на основе взаимодействия, а не тестирования на основе состояния, как объяснено здесь:

С помощью Google Mock вы можете легко создавать макеты на C++. И у людей может возникнуть соблазн использовать их повсюду. Иногда они отлично работают, а иногда вы можете обнаружить, что их очень сложно использовать. Итак, что не так в последнем случае?

Когда вы пишете тест без использования макетов, вы проверяете код и утверждаете, что он возвращает правильное значение или что система находится в ожидаемом состоянии. Это иногда называют тестированием на основе состояния.

Моки отлично подходят для того, что некоторые называют тестированием, основанным на взаимодействии: вместо проверки состояния системы в самом конце, фиктивные объекты проверяют, правильно ли они вызываются, и сообщают об ошибке, как только она возникает, давая вам точную информацию. контекст, в котором возникла ошибка. Зачастую это более эффективно и экономично, чем государственное тестирование.

Если вы выполняете тестирование на основе состояния и используете тестовый дублер только для имитации реального объекта, вам, вероятно, лучше использовать подделку. Использование макета в этом случае вызывает боль, так как моки не являются сильной стороной для выполнения сложных действий. Если вы столкнулись с этим и думаете, что моки — это отстой, вы просто используете не тот инструмент для решения своей проблемы. Или, возможно, вы пытаетесь решить не ту проблему. :-)

person nappyfalcon    schedule 08.11.2015