2011-08-02 176 views
4

我有關於工廠方法的單元測試的問題。 假設我們有以下代碼並且想要測試Foo.ToBar方法。如何單元測試工廠方法?

class Bar 
{ 
    public Bar(int someparam) 
    { 
    } 
} 

class Foo 
{ 
    int m_someprivate; 

    public Foo() 
    { 
     m_someprivate = 1; 
    } 

    public Bar TooBar() 
    { 
     return new Bar(m_someprivate); 
    } 
} 

我看到了兩種不同的方法。其中之一將是這樣的

[Test] 
void TooBarTest() 
{ 
    Foo foo = new Foo(); 

    Bar result = foo.TooBar(); 

    Assert.AreEqual(new Bar(1), result); 
} 

這是非常直截了當的。但是,我不喜歡它有兩個原因

a)我們在測試Foo類時無意測試Bar類的一部分。舉例來說,如果Bar構造函數拋出比我們的測試失敗,這是錯誤的,因爲 Foo類沒有問題。這是一個有問題的酒吧課。

b)我不喜歡在Assert new Bar(1)中使用生產代碼。我寧願使用一些常數,而不是某些代碼,例如 可能會根據某些外部狀態(例如)返回不同的結果。

我所看見的是基於建立獨立的工廠,這將創造酒吧

class Bar 
{ 
    public Bar(int someparam) 
    { 
    } 
} 

interface IBarFactory 
{ 
    Bar create(int someparam); 
} 

class BarFactory : IBarFactory 
{ 
    public Bar create(int someparam) 
    { 
     return new Bar(someparam); 
    } 
} 

class Foo 
{ 
    int m_someprivate; 
    BarFactory m_barFactory; 

    public Foo() 
    { 
     m_someprivate = 1; 
     m_barFactory = new BarFactory(); 
    } 

    public Bar TooBar() 
    { 
     return m_barFactory.create(m_someprivate); 
    } 

    public void setBarFactory(BarFactory barFactory) 
    { 
     m_barFactory = barFactory; 
    } 
} 


[Test] 
void TooBarTest() 
{ 
    Mockery mockery = new Mockery() 
    IBarFactory barFactoryMock = mockery.NewMock<IBarFactory>(); 
    Expect.Once.On(barFactoryMock).Method("create").With(new Object[] { 1 }).Will(Return.Value(new Bar(1)); 

    Foo foo = new Foo(); 
    foo.setBarFactory(barFactoryMock); 

    foo.ToBar(); 
} 

它看起來像它的更好的方法的另一種方法。但是,我不喜歡我們必須創建工廠界面,工廠,工廠設置器並使測試更復雜,只是爲了測試1行代碼。

您對此有何看法?你喜歡哪個?你有其他方法來測試它嗎?

+0

[單元測試工廠方法有一個具體類作爲返回類型]的可能重複(http://stackoverflow.com/questions/1061552/unit-testing-factory-methods-which-have-a-concrete-類作爲一種返回型) – BrokenGlass

回答

3

我同意托馬斯楊森。此外,我會在構造函數中注入IBarFactory,而不是實例化BarFactory。因此,你永遠不必碰Bar和BarFactory。相反,您可以在測試時將IBarFactory存根。

3

我肯定會去獨立工廠的方法。另外,我會將方法的名稱從ToBar更改爲其他內容。