2009-01-01 54 views
1

我正在爲MVP模式中的演示文稿類編寫單元測試。但我無法編寫模擬設置代碼。單元測試中如何處理太多的模擬期望?

我有一個演示者,當演示者的Load方法調用時,我想測試視圖應該加載類屬性,表字段,數據類型,設置演示者....所以當我有一個不同的事情時,演示者加載總是我必須增加新的期望來測試。每次測試都在變得越來越大。

[Test] 
    public void When_Presenter_Loads_View_Should_Display_Selected_Class_Properties() 
    { 
     IList<string> dataTypes =new List<string>(); 
     IClassGenerationView view = mockRepository.StrictMock<IClassGenerationView>(); 
     tableRepository = mockRepository.Stub<ITableRepository>(); 

     using(mockRepository.Record()) 
     { 
      SetupResult.For(tableRepository.GetDataTypes()).Return(dataTypes); 
      view.Presenter = null; 
      LastCall.IgnoreArguments(); 
      view.DataTypes = dataTypes; 
      view.Show(); 

      view.ClassProperties = classProperties; 
      view.TableName = "Table"; 
      view.Table = table; 
      LastCall.IgnoreArguments(); 
     } 


     using(mockRepository.Playback()) 
     { 
      ClassGenerationPresenter presenter = new ClassGenerationPresenter(view, clazz, tableRepository); 
      presenter.Load(); 
     } 
    } 

這段代碼有沒有代碼味道?我如何改進或簡化這個?

回答

1

經過漫長的不眠之夜和研究,我找到了這個解決方案。當我仔細思考時,我想出了這個。我在一次測試中測試了太多行爲。我已經改變了這樣的測試

[TestFixture] 
public class When_Presenter_Loads 
{ 
    private MockRepository mockRepository; 
    private ITableRepository tableRepository; 
    private IClass clazz; 
    private Dictionary<string, Type> properties; 
    private IClassGenerationView view; 
    private ClassGenerationPresenter presenter; 

    [SetUp] 
    public void Setup() 
    { 
     mockRepository =new MockRepository(); 
     properties = new Dictionary<string, Type>(); 

     clazz = mockRepository.DynamicMock<IClass>(); 
     view = mockRepository.DynamicMock<IClassGenerationView>(); 
     tableRepository = mockRepository.Stub<ITableRepository>(); 


    } 

    [Test] 
    public void View_Should_Display_Class_Properties() 
    { 
     using(mockRepository.Record()) 
     { 
      SetupResult.For(clazz.Properties).Return(properties); 
      view.ClassProperties = properties; 
     } 

     using(mockRepository.Playback()) 
     { 
      presenter = new ClassGenerationPresenter(view, clazz, tableRepository); 
      presenter.Load(); 
     } 
    } 

    [Test] 
    public void View_Should_Display_Class_Name_As_A_Table_Name() 
    { 
     using (mockRepository.Record()) 
     { 
      SetupResult.For(clazz.Name).Return("ClassName"); 
      view.TableName = "ClassName"; 
     } 

     using (mockRepository.Playback()) 
     { 
      presenter = new ClassGenerationPresenter(view, clazz, tableRepository); 
      presenter.Load(); 
     } 
    } 

    [Test] 
    public void View_Should_Display_SQL_Data_Types() 
    { 
     List<string> dataTypes = new List<string>(); 

     using(mockRepository.Record()) 
     { 
      SetupResult.For(tableRepository.GetDataTypes()).Return(dataTypes); 
      view.DataTypes = dataTypes; 
     } 

     using(mockRepository.Playback()) 
     { 
      presenter = new ClassGenerationPresenter(view, clazz, tableRepository); 
      presenter.Load(); 
     } 
    } 

    [Test] 
    public void View_Should_Show_Table() 
    { 
     using (mockRepository.Record()) 
     { 
      SetupResult.For(clazz.Name).Return("ClassName"); 
      view.Table = null; 
      LastCall.IgnoreArguments(); 
     } 

     using (mockRepository.Playback()) 
     { 
      presenter = new ClassGenerationPresenter(view, clazz, tableRepository); 
      presenter.Load(); 
     } 
    } 
} 

我已經使用了大量的動態模擬來測試一個時間的行爲。你也可以閱讀Dave的One Mock Per Test關於這個的文章

+0

您能否將此答案標記爲正確答案?謝謝! – guerda 2009-01-07 10:14:49

2

我一直在爲此奮鬥多年。起初,我使用MVP模式,但後來切換到Presentation Model(類似於MVVM for WPF/Silverlight)。無論如何,結果並不令人滿意,尤其是在界面變化迅速的敏捷項目中。因此,我們不再爲這些類型的類編寫測試,並且切換到SpecFlow/WaTiN以創建仍然可維護的自動化UI測試。閱讀更多關於這裏: http://www.codeproject.com/Articles/82891/BDD-using-SpecFlow-on-ASP-NET-MVC-Application

如果你仍然想爲UI邏輯編寫測試,我絕對不會使用安裝方法從你的測試中刪除一些東西。您必須能夠了解測試的原因和結果,而無需上下瀏覽。相反,使用更BDD風格的單元測試就像我在這篇博客文章已經解釋: http://www.dennisdoomen.net/2010/09/getting-more-out-of-unit-testing-in.html

一般情況下,我使用這些類BDD風格的測試,在性質上非常orchastrational,更加AAA風格測試普通類。