我有兴趣测试下面的函数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)) );
}
}
}
Node的类型为boost :: variant,其中此变体包含Foo1,Foo2,Bar1和Bar2等类型。
自由函数findFooNode
使用访问者模式来定位Foo节点(类型为Foo1或Foo2)
自由函数getCacheIdentifier
还使用访问者模式来定位Foo节点的缓存标识符。
_fooContainerCache
是一个依赖注入,在我的单元测试中被模拟。
getName也是一个自由函数,createFoo
也是如此。
所有免费功能本身都经过单元测试,并在我的代码中用于其他功能。
事情很容易在线上进行测试:
FooContainer& container = _fooContainerCache->get(id);
因为我只需要在模拟中检查期望的id是否被呈现给get函数。
但是,要在此行之后测试代码,我需要检查对我的模拟引用返回的FooContainer所做的更改。但是,如果createFoo将来要改变,我知道它会改变,这导致我必须更改createFoo和navigateFoo的单元测试。但是,如果我依赖注入一个FooFactory,我会避免这个问题,而是这样做:
container.push_back( _fooFactory->create( getData(*fooNodeI) ));
然后我也可以在我的单元测试中模拟这个功能。如果此接口背后的行为发生变化,那么它不会导致我必须重写navigateFoo的测试。
然而,当我编写createFoo时,我从未觉得应该将其作为接口实现,所以现在我觉得我只是为了能够编写更好的测试而添加一个接口。然后问题出现了,我应该为任何其他免费功能提供界面吗?在这方面有没有经验法则?
答案 0 :(得分:1)
然后出现了问题,我是否应该为其他任何免费功能提供界面?
SOLID每个类都应该有一个接口是必不可少的。我个人并不是100%遵循这条规则。
这方面有没有经验法则?
遵循你的直觉。如果您觉得您需要一个类需要一个接口来简化单元测试,那么只需添加一个接口即可。它将简化您和维护者的生活。
但请注意YAGNI。
此外,this question可能会产生一些疑问。