Бесплатные функции и юнит-тестирование

Я заинтересован в тестировании функции navigateFoo ниже:

virtual void navigateFoo(const vector<Node>& nodes)
{
// find the foo node in the list of nodes
Nodes::const_iterator fooNodeI = findFooNode(nodes);

// if we have found the foo node
if(fooNodeI!=nodes.end())
{
// the id for retrieving the associated Foo Container from the cache
std::string id = getCacheIdentifier(*fooNodeI);
// the Foo Container associated with the Foo Node
FooContainer& container = _fooContainerCache->get(id);

// the name of the Foo item within the Foo Container
std::string name = getName(*fooNodeI);
// if foo is not found in the associated container, add it
if(findFoo(name, container)==container.end())
{
container.push_back( createFoo(getData(*fooNodeI)) );
}
}
}

Узел имеет тип Boost :: Вариант, где этот вариант содержит типы Foo1, Foo2, Bar1 и Bar2 и т. Д.

Свободная функция findFooNode использует шаблон посетителя для поиска узла Foo (типа Foo1 или Foo2)

Свободная функция getCacheIdentifier также использует шаблон посетителя, чтобы найти идентификатор кэша для Foo Node.

_fooContainerCache является инъекцией зависимостей и проверяется в моем модульном тесте.

getName снова бесплатная функция, как createFoo,

Все бесплатные функции сами тестируются модулем и используются в других функциях моего кода.

Вещи легко проверяются вплоть до линии:

FooContainer& container = _fooContainerCache->get(id);

так как мне нужно только проверить с макетом, что ожидаемый идентификатор представлен функции get.

Однако, чтобы протестировать код после этой строки, мне нужно проверить изменения, внесенные в FooContainer, возвращенный по ссылке из моего макета. Однако, если createFoo должен был измениться в будущем, что я знаю, это приведет к тому, что мне придется изменить мои модульные тесты для createFoo и navigateFoo. Однако, если бы я вместо этого вставил зависимость FooFactory, я бы избежал этой проблемы, сделав это вместо этого:

container.push_back( _fooFactory->create( getData(*fooNodeI) ));

Затем я могу смоделировать эту функцию и в моем модульном тесте. Если поведение этого интерфейса изменится, то это не приведет к необходимости переписывать тесты для navigateFoo.

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

0

Решение

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

Это важно для SOLID что у каждого класса должен быть интерфейс. Я лично не следую этому правилу на 100%.

Есть ли какие-то практические правила в этом отношении?

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

Тем не менее, следите за YAGNI.


Также, этот вопрос может очистить некоторые сомнения.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]