2013-04-29 158 views
0

我感興趣的是下面的測試功能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時,我從來沒有覺得它應該作爲一個接口來實現,所以現在我覺得我只是爲了能夠編寫更好的測試而添加一個接口。然後問題出現了,我是否應該爲我的其他免費功能提供接口?這方面有沒有經驗法則?

+0

看起來你正在測試太小的水平。用這樣的模擬測試幾乎沒有什麼價值,因爲即使可能沒有可觀察到的客戶變化,更改代碼也會中斷測試。 – 2013-04-29 14:08:52

+0

@Billy ONeal你的意思是說,如果你正在用push_back測試上面的代碼行,那麼你只需檢查FooContainer對象的大小是否增加了一個,然後把它留在那裏呢? – Baz 2013-04-29 14:20:39

+0

@Baz(如果可能的話)我也會以某種方式檢查它的內容,而不僅僅是容器的大小。 – 2013-04-29 14:22:45

回答

1

然後問題出現了,我是否應該爲我的任何其他自由函數創建接口?

對於SOLID這是至關重要的,每個類都應該有一個接口。我個人不遵循這個規則100%。

在這方面是否有任何經驗法則?

追隨你的直覺。如果你覺得你需要一個類需要一個接口來簡化單元測試,那麼只需添加一個接口即可。它將簡化你和維護者的生活。請注意0​​。


此外,this question可能會清晰一些疑惑。

+0

這將導致對navigateFoo定義的類進行大量的依賴注入,因爲我認爲這些自由函數都不屬於同一個接口。這是否意味着navigateFoo在你看來設計得不好,應該把它分解成更小的部分? – Baz 2013-04-29 14:07:27

+0

ISP不是「每個班級都有一個接口」。這意味着「有大量的小接口,而不是幾個大接口」。它本質上是接口的SRP。 – 2013-04-29 14:07:41

+0

@BЈовић此外,std算法通常是免費函數,它們沒有接口。 – Baz 2013-04-29 14:09:12