2010-02-25 82 views
0

我剛剛開始使用MSpec(帶有James Broome的AutoMocking)和RhinoMocks的BDD/TDD。下面是從我的實踐項目的摘錄:我應該測試一個存根方法是否被調用?

namespace Tests.VideoStore.Controllers 
{ 
    public abstract class context_for_movie_controller : 
    Specification<MovieController> 
    { 
     private static IList<Movie> movies; 
     protected static IMovieRepository _movieRepository; 
     protected static ActionResult _result; 
     protected static string title; 
     protected static string director; 

     Establish context =() => 
     { 
      _movieRepository = DependencyOf<IMovieRepository>(); 
     }; 
    } 

    [Subject(typeof(MovieController))] 
    public class when_searching_for_movies_with_director : 
    context_for_movie_controller 
    { 
     Establish context =() => 
     { 
      title = null; 
      director = "James Cameron"; 

      var movie4 = new Movie { 
       Title = "Terminator", Director = "James Cameron"}; 
      var movie6 = new Movie { 
       Title = "Avatar", Director = "James Cameron"}; 

      movies = new List<Movie> {movie4, movie6}; 

      // Repository returns all movies. 
      _movieRepository.Stub(x => x.FindMovies(title, director)) 
      .Return(movies); 
     }; 

     Because of =() => _result = subject.Find(title, director); 

     It should_fetch_movies_from_the_repository =() => 
      _movieRepository.AssertWasCalled(x => 
       x.FindMovies(title, director)); 

     It should_return_a_list_of_movies_matching_the_director =() => 
      _result.ShouldBeAView().And() 
      .ShouldHaveModelOfType<IEnumerable<Movie>>) 
      .And().ShouldContainOnly(movies); 
    } 

正如你所看到的,我掐滅了FindMovies上MovieRepository類()方法。然後我打電話給MoviesController.Find()動作。我的問題是,如果有一個斷言來檢查控制器是否調用了存根方法(FindMovies)?或者,我應該只關心返回的結果,而不關心它從何處被帶走?此外,規範中的「should_fetch_movies_from_the_repository」看起來很像工程任務,而不是客戶可能理解的東西 - 是否在BDD中佔有一席之地?

回答

1

斷言遵循的一般規則是您對輸出交互而不是輸入交互進行斷言。

FindMovies存根將一個「電影」集合返回給調用它的類,然後通過「它應該返回與導演匹配的電影列表」斷言來驗證類是否收到了正確的列表。如果FindMovies方法是而不是調用,則此斷言將失敗。

因此,您不需要針對FindMovies方法斷言調用。

爲了對比這一點,如果你有一個純粹輸出的模擬或存根 - 比方說一個由Presenter類調用的IView接口,那麼你確實想要對所調用的IView進行斷言。例如,下面的代碼:


public class MyPresenter 
{ 
    ... other code here 

    public DoSomething() 
    { 
    IList data = GetSomeData(); 
    myView.DisplayData(data); 

    } 
} 

你想斷言,view.DisplayData方法被調用在這種情況下,因爲你不是檢索從這個函數可以由另一個測試斷言什麼。

至於「從倉庫取回」 - 當然你的客戶關心這一點。他們希望系統將電影保存到存儲中並從存儲中加載它們。但是... FindMovies調用是被測試類的輸入,所以根本沒有必要進行這種聲明或測試。如果未調用FindMovies方法,則另一個測試將失敗,並讓您知道存在問題。

+0

沒錯,現在我發現如果我在控制器操作中沒有使用FindMovies,測試會失敗。但是,如果我通過不同的方式創建相同的列表而不是調用FindMovies,測試會通過。我想我不應該關心數據來自哪裏,只要它是有效的,對吧? – 2010-02-26 10:21:22

+1

你做,你不在乎。您關心的是數據是從外部存儲機制加載的 - 但您並不在乎它是如何從該存儲機制加載的。真正的好處是你不會創建脆弱的測試,當你改變你的API或實現時開始失敗。如果您決定使用一種名爲「FindMoviesInCache」的緩存機制將您的調用替換爲FindMovies,例如,只要存根的FindMoviesInCache返回正確的數據,您的測試仍會通過。 – 2010-02-26 12:29:32

相關問題