Как Вы дразните классы, которые используют RAII в C++

static deleteById(id, callback) {
  console.log('deleteById', { id });
  getProductsFromFile(products => {
    let deletedProduct = null;
    let updatedProducts = [];

    for(const product of products) {
      if(product.id === id) {
        deletedProduct = product
      } else {
        updatedProducts.push(product);
      }
    }

    if (!deletedProduct) {
      console.log('deleteById: Product not found', { id });
      callback();
    } else {
      fs.writeFile(p, JSON.stringify(updatedProducts), err => {
        if (!err) {
          console.log('deleteById: Product', deletedProduct);
          Cart.deleteProduct(id, deletedProduct.price, callback);
        }
      });
    }
  })
}
9
задан Gordon Wilson 12 October 2008 в 16:47
поделиться

4 ответа

Вы вместо этого делаете интерфейс, который описывает тип, и имейте и реальный класс и ложный класс, наследовались этому. Таким образом, если Вы имели:

class RAIIClass {
 public:
  RAIIClass(Foo* f);
  ~RAIIClass();
  bool DoOperation();

 private:
  ...
};

Вы сделали бы интерфейс как:

class MockableInterface {
 public:
  MockableInterface(Foo* f);
  virtual ~MockableInterface();
  virtual bool DoOperation() = 0;
};

И пойдите оттуда.

12
ответ дан 4 December 2019 в 11:08
поделиться

pimpl идиома могла бы подойти Вам также. Создайте свой класс Потока с конкретной реализацией, которую он вводит внизу. Если Вы вставляете право #defines и #ifdefs, Ваша реализация может измениться при включении поблочного тестирования что означает, что можно переключиться между реальной реализацией и дразнившей в зависимости от того, что Вы пытаетесь выполнить.

1
ответ дан 4 December 2019 в 11:08
поделиться

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

По-видимому, Вы хотите использовать другую функцию или класс, который использует класс, который Вы хотите дразнить (иначе, решение тривиально). Позволяет называют бывшего "Пользователя" и последнего "Дразнившими". Вот некоторые возможности:

  1. Измените Пользователя для использования абстрактной версии Дразнивших (Вы добираетесь для выбора какой абстракция для использования: наследование, обратный вызов, шаблоны, и т.д.....).
  2. Скомпилируйте другую версию Дразнивших за Ваш код тестирования (например, #def код RAII при компиляции тестов).
  3. Дразнили принимают, что флаг конструктора выключает свое поведение. Я лично постарался бы не делать это.
  4. Просто высосите стоимость выделения ресурса.
  5. Пропустите тест.

Последние два могут быть Вашим единственным обращением за помощью, если Вы не можете изменить Пользователя или Дразнивший. Если можно изменить Пользователя, и Вы полагаете, что разработка Вашего кода, чтобы быть тестируемой важна, то необходимо исследовать первую опцию перед любыми из других. Обратите внимание, что может быть компромисс между созданием Вашего универсального/гибкого кода и хранением его прост, оба из которых являются замечательными качествами.

6
ответ дан 4 December 2019 в 11:08
поделиться

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

В тестовое время Вы загружаете насмешку, которая не создает потоков, но просто вперед к методу Вы хотите протестировать.

class Base{
 protected:
  Base* decorated;
 public:
  virtual void method(void)=0;
};
class Final: public Base{
  void method(void) { Thread athread; decorated->method(); } // I expect Final to do something with athread
};
class TestBase: public Base{
  void method(void) { decorated->method(); }
};
0
ответ дан 4 December 2019 в 11:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: