2011-12-13 50 views
0

對於TDD而言是相當新穎的;首先想給BDD一個嘗試。我正在使用MVP用戶界面演示模式框架,並且我正在嘗試使用SubSpec和XUnit編寫我的第一個測試,但是當我向repo進行調用時,我從演示者處獲得NullReferenceException。具有SubSpec和XUnit的BDD NullReferenceException

我確定答案是顯而易見的,但它給了我。另外,看起來我的測試更關注於Presentation Pattern的細節 - 我相信它的工作原理,可能不需要像下面那樣進行測試(即提升view.load事件),但我不能想象另一種方式。歡迎任何關於更好測試的建議。

我的單元測試:

[Specification] 
    public void ViewLoad_WhenTheView.LoadEventIsRaised_ViewLoadShouldGetAll() 
    { 
     var view = MockRepository.GenerateMock<IOpenJobsView>(); 
     var repository = MockRepository.GenerateMock<IOpenJobsRepository>(); 
     var model = new OpenJobsModel().OpenJobs; 
     var openJobs = new List<OpenJob>(); 
     var jobsFromModel = view.Stub(v => v.Model.OpenJobs).Return(model); 
     var jobsFromRepo = repository.Stub(r => r.GetAll()).Return(openJobs); 
     var presenter = default(OpenJobsPresenter); 

     "Given an openJobsPresenter" 
      .Context(() => presenter = new OpenJobsPresenter(view, repository)); 

     "when the view loads" 
      .Do(() => view.Raise(v => v.Load += presenter.ViewLoad, view, new EventArgs())); 

     "the object subscribed to the event should result in a call to GetAll" 
      .Assert(() => repository.AssertWasCalled(o => o.GetAll())); 
     "the results from the call to GetAll should be equal to the model" 
      .Assert(() => Assert.Equal(jobsFromModel, jobsFromRepo)); 

我主講人:

public class OpenJobsPresenter : Presenter<IOpenJobsView> 
{ 
    readonly IOpenJobsRepository openJobsRepository; 

    public OpenJobsPresenter(IOpenJobsView view, IOpenJobsRepository openJobsRepository) : base(view) 
    { 
     this.openJobsRepository = openJobsRepository; 
     View.Load += ViewLoad; 
    } 

    public void ViewLoad(object sender, System.EventArgs e) 
    { 
     View.Model.OpenJobs = openJobsRepository.GetAll(); //Getting NullReferenceException here 
    } 
} 

回答

0

確定。我能夠弄清楚這一點。空引用是由於模型未被視圖初始化。所以我在視圖上挖掘了模型 - 就是這樣做的。

我清理了我的測試,並將其與待測系統一起包含在一個完整的解決方案中。

單元測試:

public class OpenJobsPresenterTests 
{ 
    readonly OpenJobsModel _model; 
    readonly IOpenJobsView _view; 
    readonly IOpenJobsRepository _repo; 

    public OpenJobsPresenterTests() 
    { 
     _model = MockRepository.GenerateMock<OpenJobsModel>(); 
     _view = MockRepository.GenerateMock<IOpenJobsView>(); 
     _repo = MockRepository.GenerateMock<IOpenJobsRepository>(); 
    } 

    [Specification] 
    public void OpenJobsPresenterShouldGetAllOpenJobsOnViewLoad() 
    { 
     var presenter = default(OpenJobsPresenter); 
     var openJobs = new List<OpenJob>(); 
     _view.Stub(v => v.Model).Return(_model); 
     _repo.Stub(d => d.GetAll()).Return(openJobs); 

     "Given the OpenJobsPresenter" 
      .Context(() => presenter = new OpenJobsPresenter(_view, _repo)); 

     "when the view's load event is raised" 
      .Do(() => _view.Raise(d => d.Load += presenter.OnViewLoad, _view, new EventArgs())); 

     "the event subscriber should get all open jobs" 
      .Assert(() => _repo.AssertWasCalled(r => r.GetAll())); 

     "the model should equal the results returned" 
      .Assert(() => _view.Model.OpenJobs.ShouldBe(openJobs)); 
    } 

} 

SUT:

public class OpenJobsPresenter : Presenter<IOpenJobsView> 
{ 
    readonly IOpenJobsRepository openJobsRepository; 

    public OpenJobsPresenter(IOpenJobsView view, IOpenJobsRepository openJobsRepository) : base(view) 
    { 
     this.openJobsRepository = openJobsRepository; 
     View.Load += OnViewLoad; 
    } 

    public void OnViewLoad(object sender, System.EventArgs e) 
    { 
     View.Model.OpenJobs = openJobsRepository.GetAll(); 
    } 
}