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);
}
});
}
})
}
Вы вместо этого делаете интерфейс, который описывает тип, и имейте и реальный класс и ложный класс, наследовались этому. Таким образом, если Вы имели:
class RAIIClass {
public:
RAIIClass(Foo* f);
~RAIIClass();
bool DoOperation();
private:
...
};
Вы сделали бы интерфейс как:
class MockableInterface {
public:
MockableInterface(Foo* f);
virtual ~MockableInterface();
virtual bool DoOperation() = 0;
};
И пойдите оттуда.
pimpl идиома могла бы подойти Вам также. Создайте свой класс Потока с конкретной реализацией, которую он вводит внизу. Если Вы вставляете право #defines и #ifdefs, Ваша реализация может измениться при включении поблочного тестирования что означает, что можно переключиться между реальной реализацией и дразнившей в зависимости от того, что Вы пытаетесь выполнить.
В первую очередь, это - не обязательно неблагоразумная вещь, что Ваши классы могли бы быть хорошо разработаны для их использования, но плохо разработаны для тестирования. Не все легко протестировать.
По-видимому, Вы хотите использовать другую функцию или класс, который использует класс, который Вы хотите дразнить (иначе, решение тривиально). Позволяет называют бывшего "Пользователя" и последнего "Дразнившими". Вот некоторые возможности:
Последние два могут быть Вашим единственным обращением за помощью, если Вы не можете изменить Пользователя или Дразнивший. Если можно изменить Пользователя, и Вы полагаете, что разработка Вашего кода, чтобы быть тестируемой важна, то необходимо исследовать первую опцию перед любыми из других. Обратите внимание, что может быть компромисс между созданием Вашего универсального/гибкого кода и хранением его прост, оба из которых являются замечательными качествами.
Одна техника, которую я использовал, состоит в том, чтобы использовать некоторую форму декоратора. Ваш заключительный код имеет метод, который создает его экземпляр на стеке и затем называет тот же метод, но на участнике, который является указателем на Ваш базовый класс. Когда тот вызов возвращается, Ваши возвраты метода, уничтожающие экземпляр, Вы создали.
В тестовое время Вы загружаете насмешку, которая не создает потоков, но просто вперед к методу Вы хотите протестировать.
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(); }
};