我感興趣的是下面的測試功能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)));
}
}
}
節點的類型爲升壓變型,在這個變體包含類型Foo1和Foo2,BAR1和BAR2等:: 。
自由功能findFooNode
使用訪問者模式來定位符節點
自由功能getCacheIdentifier
還使用訪問者模式來定位爲Foo節點的緩存標識(Foo1型或foo2的的)。
_fooContainerCache
是依賴注入,並在我的單元測試中被嘲弄。
getName和createFoo
一樣是一項免費功能。
所有的免費功能本身都是經過單元測試的,並在我的代碼中用於其他功能。
事情容易地測試到行:
FooContainer& container = _fooContainerCache->get(id);
,因爲我只需要與模擬檢查預期的ID呈現給get函數。
但是,爲了測試此行後面的代碼,我需要檢查從我的模擬中引用返回的FooContainer所做的更改。然而,如果createFoo將來會改變,我知道它會這樣,這導致我必須更改我的單元測試for createFoo和navigateFoo。但是,如果我是依賴注入一FooFactory相反,我會避免這個問題,而不是做這樣的:
container.push_back(_fooFactory->create(getData(*fooNodeI)));
然後我也嘲笑這個功能在我的單元測試。如果這個接口背後的行爲改變了,那麼它不會導致我必須重寫navigateFoo的測試。
但是,當我編寫createFoo時,我從來沒有覺得它應該作爲一個接口來實現,所以現在我覺得我只是爲了能夠編寫更好的測試而添加一個接口。然後問題出現了,我是否應該爲我的其他免費功能提供接口?這方面有沒有經驗法則?
看起來你正在測試太小的水平。用這樣的模擬測試幾乎沒有什麼價值,因爲即使可能沒有可觀察到的客戶變化,更改代碼也會中斷測試。 – 2013-04-29 14:08:52
@Billy ONeal你的意思是說,如果你正在用push_back測試上面的代碼行,那麼你只需檢查FooContainer對象的大小是否增加了一個,然後把它留在那裏呢? – Baz 2013-04-29 14:20:39
@Baz(如果可能的話)我也會以某種方式檢查它的內容,而不僅僅是容器的大小。 – 2013-04-29 14:22:45