带有 SubSpec 和 XUnit NullReferenceException 的 BDD

发布于 2024-12-21 06:17:04 字数 1939 浏览 4 评论 0原文

对 TDD 还很陌生;想先尝试一下 BDD。我正在使用 MVP UI 演示模式框架,并尝试使用 SubSpec 和 XUnit 编写我的第一个测试,但是当我调用存储库时,我从演示者处收到 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
    }
}

Fairly new to TDD; want to give BDD a try first. I'm using an MVP UI Presentation Pattern Framework and I'm trying to write my first test using SubSpec and XUnit but I'm getting a NullReferenceException from my presenter when I make a call to the repo.

I'm sure the answer is obvious, but its got me. Also, it appears that my test is concerned more with the details of the Presentation Pattern -- I trust that it works and probably doesn't need to be tested like below (i.e. raising the view.load event) but I could'nt think of another way. Any suggestions for a better test are welcomed.

My Unit Test:

[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));

My Presenter:

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
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

黑色毁心梦 2024-12-28 06:17:04

好的。我能够弄清楚这一点。空引用是由于视图未初始化模型造成的。所以我把视图上的模型删掉了——这样就完成了。

我清理了我的测试,并将其与被测系统一起包含在内,以获得完整的解决方案。

单元测试:

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();
    }
}

Ok. I was able to figure this out. The null reference was due to the model not being initialized by the view. So I stubbed out the model on the view -- that did it.

I cleaned up my test and included it along with the system under test for a complete solution.

Unit Test:

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文