Могу ли я скопировать макет объекта Google после установки ожиданий?

Я хочу добавить служебную функцию в свой класс тестовых приспособлений, которая будет возвращать макет с определенным набором ожиданий/действий.

E.g.:

class MockListener: public Listener
{
    // Google mock method.
};

class MyTest: public testing::Test
{
public:
    MockListener getSpecialListener()
    {
        MockListener special;
        EXPECT_CALL(special, /** Some special behaviour e.g. WillRepeatedly(Invoke( */ );
        return special;
    }
};

TEST_F(MyTest, MyTestUsingSpecialListener)
{
    MockListener special = getSpecialListener();

    // Do something with special.
}

К сожалению, я получаю:

error: use of deleted function ‘MockListener ::MockListener (MockListener &&)’

Итак, я предполагаю, что макеты не могут быть скопированы? Почему, и если да, то есть ли другой элегантный способ получить функцию для создания готового макета с уже установленными ожиданиями/действиями?

Очевидно, я могу заставить getSpecialListener возвращать MockListener&, но тогда ему не нужно быть членом MyTest, и поскольку только некоторые тесты используют этот конкретный макет (и я должен заполнять поведение макета только в том случае, если тест его использует) было бы менее чисто.


person nappyfalcon    schedule 09.10.2015    source источник
comment
Я подозреваю, что ожидание вызова относится к конкретному экземпляру макета, поэтому они не будут автоматически отложены до копий макета (имеет ли это смысл в любом случае?). Поэтому я предполагаю, что макеты нельзя копировать? Классы макетов для SE должны быть копируемыми IIRC.   -  person πάντα ῥεῖ    schedule 09.10.2015
comment
К сожалению, следующий сообщение, похоже, доказывает, что я ошибаюсь в воспоминаниях. Кажется, что любые фиктивные объекты не могут быть скопированы.   -  person πάντα ῥεῖ    schedule 09.10.2015
comment
Да, просто удалив MOCK_METHODX и заменив его обычной реализацией метода Listener, он скомпилируется. Вы правы, этот пост в значительной степени объясняет это. :-(   -  person nappyfalcon    schedule 09.10.2015
comment
А вы пытались явно реализовать поведение копирования? Хотя ожидания ни в коем случае нельзя копировать. Я бы попробовал использовать отдельную функцию, чтобы создать ожидания для произвольных фиктивных экземпляров, которые будут использоваться в настройке.   -  person πάντα ῥεῖ    schedule 09.10.2015
comment
Мое главное намерение состояло в том, чтобы ожидания были скопированы. А в упомянутом вами посте написано, что их не будет.   -  person nappyfalcon    schedule 09.10.2015
comment
Что ж, как уже упоминалось, предоставьте дополнительную вспомогательную функцию, которая устанавливает ожидания для произвольных фиктивных экземпляров.   -  person πάντα ῥεῖ    schedule 09.10.2015
comment
вернуться через std::unique_ptr...   -  person PiotrNycz    schedule 09.10.2015


Ответы (2)


Мок-объекты нельзя копировать, но вы можете написать фабричный метод, который возвращает указатель на вновь созданный фиктивный объект. Чтобы упростить владение объектом, вы можете использовать std::unique_ptr.

std::unique_ptr<MockListener> getSpecialListener() {
  MockListener* special = new MockListener();
  EXPECT_CALL(*special, SomeMethod()).WillRepeatedly(DoStuff());
  return std::unique_ptr<MockListener>(special);
}

TEST_F(MyTest, MyTestUsingSpecialListener) {
  std::unique_ptr<MockListener> special = getSpecialListener();

  // Do something with *special.
}
person VladLosev    schedule 10.10.2015

Что ж, кажется невозможным правильно копировать экземпляры фиктивных классов, особенно не глубокое копирование каких-либо ожиданий, связанных с ними.

Что вы можете сделать, так это предоставить вспомогательные функции в вашем тестовом классе, которые устанавливают определенные ожидания для фиктивных экземпляров, например:

class MyTest: public testing::Test {
public:
    MockListener& setSpecialListenerExpectations(MockListener& special) 
             // ^                                            ^
    {
        EXPECT_CALL(special, /** Some special behaviour e.g.  WillRepeatedly(Invoke( */ );
        return special;
    }
};

и сделайте их специальными в тестовом примере:

TEST_F(MyTest, MyTestUsingSpecialListener) {
    MockListener special;
    setSpecialListenerExpectations(special);

    // Do something with special.
}
person πάντα ῥεῖ    schedule 09.10.2015