Sunday, February 07, 2010

Day 4 of 5 Day TDD Kata: "AddTaxesPresenter Displays Tax Grid and Adds New Taxes"

I've just completed Day 4 of the 5 Day TDD Kata.

The project is growing into multiple tests and classes, so I will only post a brief code sample below; full samples are posted to github here.

Here's the kata:

DAY 4: AddTaxesPresenter DISPLAYS TAX GRID AND ADDS NEW TAXES
  1. Create namespaces for Presenter and View.
  2. Create TaxesPresenterTests with mocked ITaxesService and ITaxesView.
  3. Create ITaxesView.ShowTaxes event with default EventHandler. Verify that TaxesPresenter attaches an event handler to ShowTaxes in its constructor.
  4. Verify that the view's ShowTaxes event, when raised, is handled by TaxesPresenter's event handler, which should assign ITaxesService.Taxes to ITaxesView.TaxesDisplay.
  5. Create ITaxesView.AddTax event with default EventHandler. Update your first and second tests to verify that TaxPresenter's constructor now also assigns the event handler for AddTaxEvent.
  6. Verify that when AddTax event is raised, it is handled by TaxesPresenter's event handler as follows:
    a) Each required Tax constructor parameter exists as a get property of ITaxesView, and each of those properties is called (returning a value specified in the mock).
    b) it creates Tax instance with the property values assigned to the mock.

    c) it calls ITaxesService.AddTax() to add the Tax.
    d) it refreshes ITaxesView.TaxesDisplay from ITaxesService.Taxes, which includes the just-added Tax instance.
TaxesPresenterTests.cs

[TestFixture]
public class TaxesPresenterTests
{
    private MockRepository _mockRepository;
    private ITaxesView _mockTaxesView;
    private ITaxesService _mockTaxesService;

    [SetUp]
    public void SetUp()
    {
        _mockRepository = new MockRepository();
        _mockTaxesService = _mockRepository.StrictMock();
        _mockTaxesView = _mockRepository.StrictMock();
    }

    [TearDown]
    public void TearDown()
    {
        _mockRepository.VerifyAll();
    }

    [Test]
    public void TaxesPresenterAttachesViewEventHandlersOnConstruction()
    {
        _mockTaxesView.ShowTaxes += null;
        LastCall.IgnoreArguments();
        _mockTaxesView.AddTax += null;
        LastCall.IgnoreArguments();

        _mockRepository.ReplayAll();

        var taxesPresenter = new TaxesPresenter(_mockTaxesService, _mockTaxesView);
    }

    [Test]
    public void ShowTaxesEventDisplayAllTaxes()
    {
        _mockTaxesView.ShowTaxes += null;
        var showTaxesEventRaiser = LastCall.IgnoreArguments().GetEventRaiser();
        _mockTaxesView.AddTax += null;
        LastCall.IgnoreArguments();
        var taxes = new List();
        Expect.Call(_mockTaxesService.Taxes).Return(taxes);
        _mockTaxesView.TaxesDisplay = taxes;

        _mockRepository.ReplayAll();

        var taxesPresenter = new TaxesPresenter(_mockTaxesService, _mockTaxesView);
        showTaxesEventRaiser.Raise(_mockTaxesView, EventArgs.Empty);
    }

    [Test]
    public void AddTaxEventCallsITaxesServiceAddAndReassignsToGridWithExtraRow()
    {
        _mockTaxesView.ShowTaxes += null;
        LastCall.IgnoreArguments();
        _mockTaxesView.AddTax += null;
        var addTaxEventRaiser = LastCall.IgnoreArguments().GetEventRaiser();
        const string taxType = "pstTax";
        DateTime? startDate = DateTime.Today;
        DateTime? endDate = DateTime.Today.AddYears(1);
        const JurisdictionEnum jurisdiction = JurisdictionEnum.ProvinceState;
        const int percent = 5;
        Expect.Call(_mockTaxesView.TaxType).Return(taxType);
        Expect.Call(_mockTaxesView.StartDate).Return(startDate);
        Expect.Call(_mockTaxesView.EndDate).Return(endDate);
        Expect.Call(_mockTaxesView.Jurisdiction).Return(jurisdiction);
        Expect.Call(_mockTaxesView.Percent).Return(percent);
        var tax = new Tax(taxType, startDate, endDate, jurisdiction, percent);
        _mockTaxesService.AddTax(tax);
        var taxes = new List { tax };
        Expect.Call(_mockTaxesService.Taxes).Return(taxes);
        _mockTaxesView.TaxesDisplay = taxes;

        _mockRepository.ReplayAll();

        var taxesPresenter = new TaxesPresenter(_mockTaxesService, _mockTaxesView);
        addTaxEventRaiser.Raise(_mockTaxesView, EventArgs.Empty);
    }
}


TaxesPresenter.cs


public class TaxesPresenter
{
    private readonly ITaxesService _taxesService;
    private readonly ITaxesView _taxesView;

    public TaxesPresenter(ITaxesService taxesService, ITaxesView taxesView)
    {
        _taxesService = taxesService;
        _taxesView = taxesView;

        _taxesView.ShowTaxes += new System.EventHandler(TaxesViewShowTaxes);
        _taxesView.AddTax += new System.EventHandler(TaxesViewAddTax);
    }

    void TaxesViewAddTax(object sender, System.EventArgs e)
    {
        var tax = new Tax(_taxesView.TaxType, _taxesView.StartDate, _taxesView.EndDate, _taxesView.Jurisdiction, _taxesView.Percent);
        _taxesService.AddTax(tax);
        DisplayAllTaxes();
    }

    void TaxesViewShowTaxes(object sender, System.EventArgs e)
    {
        DisplayAllTaxes();
    }

    private void DisplayAllTaxes()
    {
        _taxesView.TaxesDisplay = _taxesService.Taxes;
    }
}

No comments: