TDD相当新鲜;想先试试BDD。我正在使用MVP UI表示模式框架,我正在尝试使用SubSpec和XUnit编写我的第一个测试,但是当我调用repo时,我从我的演示者那里得到了NullReferenceException。
我确信答案是显而易见的,但是它让我感到满意。此外,我的测试似乎更多地关注演示模式的细节 - 我相信它的工作原理并且可能不需要像下面那样进行测试(即提升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 :(得分: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();
}
}