Как вы разрабатываете приложение на C ++, чтобы Mock Objects было проще в использовании? - PullRequest
3 голосов
/ 14 сентября 2009

Я никогда не разрабатывал с использованием Test Driven Development, и я никогда не использовал Mock Objects для модульного тестирования. Я всегда тестировал модульные простые объекты, которые не включают в себя другие аспекты приложения, а затем переходил к менее простым объектам, которые ссылаются только на объекты, которые уже были модульно протестированы. Это имеет тенденцию прогрессировать до тех пор, пока последний «модульный» тест не станет компонентным.

Какие методы проектирования используются, чтобы сделать замену внутренних классов на объекты-макеты как можно проще?

Например, в моем коде я бы включил заголовочный файл для myDataClass в myWorkerClass. myDataClass создается myWorkerClass, а его время жизни связано с myWorkerClass. Как вы можете настроить его так, чтобы он включал фиктивный myDataClass, когда включение включено?

Ответы [ 3 ]

4 голосов
/ 14 сентября 2009

Ответ для начинающих будет:

  • в тестируемом классе не используют тип издеваются, используйте его интерфейс
  • при тестировании предоставить другая реализация издевательского объекта интерфейс
//Common header
class ObjectInterface {
public:
  virtual void doThings()=0;
};

//Release
class RealObject: public ObjectInterface {
public:
  virtual void doThings(){
    //Complicated work here
  }
};

//Testing 
class MockedObject: public ObjectInterface {
public:
  virtual void doThings(){
    //Not so complicated work here
  }
};

//Common header
class TestedClass {
public:
  void useObject(ObjectInterface & object) {
    object->doThings();
  }
};


//Unit test
TestedClass toTest;
MockedObject mockedObject;
toTest.useObject(mockedObject);
2 голосов
/ 14 сентября 2009

Можно попытаться адаптировать свой код в соответствии с шаблоном (Abstract) Factory Design , в результате чего можно использовать другую фабрику в среде модульного тестирования, которая создаст ваши фиктивные объекты.

0 голосов
/ 14 сентября 2009

Один из способов - не связывать ваши классы таким образом.

Используя ваш пример:

myDataClass будет чисто виртуальным классом. Это будет иметь как минимум 2 реализации: «реальную» и макетную.

Ваш тестовый код может внедрить ложный экземпляр, имея 2 конструктора, один из которых принимает myDataClass, а другой - нет. Посмотрите код ниже для примера.

class myWorkerClass {
public:
    myWorkerClass(myDataClass * dc) : m_dc(dc) {}
    myWorkerClass() : m_dc(new MyRealDataClass()) { }
    ~myWorkerClass { delete m_dc; }

private:
    myDataClass *m_dc;
}

Теперь вы можете предоставить любую реализацию myDataClass для myWorkerClass, которую вы хотите. Если вы не предоставляете реализацию, тогда ваш код возвращается к «реальной» реализации.

Другой метод - использовать шаблон Factory для создания экземпляров ваших объектов. Ваш тестовый код может установить некоторый флаг на фабрике, который создает экземпляры myDataClass и заставляет его создавать фиктивный объект вместо реального. Я предпочитаю первый метод, так как для меня его немного проще использовать (плюс мне не нужно поддерживать заводской класс для всего, что я хочу протестировать)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...