Monday, February 13, 2012

TDD with Objective-C and Calculator Kata (using JetBrains' AppCode)

I've just created a 1 hour tutorial/screencast that demonstrates TDD in objective-C (iOS 5) via Roy Osherove's Calculator Kata. The screencast primarily uses JetBrains' new AppCode IDE for objective-C, but it also flips occasionally into XCode 4.2 to set up a storyboard with a simple UIViewController that connects to the TDD-created Calculator class.

The screencast demonstrates a variety of layouts and keyboard shortcuts for AppCode (and to a lesser extent, XCode) as well as covering a number of language features of objective-C.

Please have a look, and if you have any questions, send me a comment at my twitter account.

Screencast: Learning Objective-C via TDD and Calculator Kata

Sunday, February 12, 2012

DDD Kata, Part 4 (Service Layer with Mocks)

Pre-Requisite: DDD Kata Part 3

Kata Review
In part 2 of the kata, you built a simple service test to demonstrate the passing of the Item from the Inventory aggregate root to the Invoice aggregate root. In part 3 of the kata, you created IUnitOfWork interface to manage atomic transactions with commit and rollbacks.

Now we need to design the real service.

In this test we will "inject" repository interfaces into the service class constructor to do the work of persisting the state changes to our domain entities. The UnitOfWork we created in part 3 of the kata will assist us in this effort.

Completed kata example on github: DDD Kata Part 4 sample code (github)

NOTE   If you haven't already download RhinoMocks, download it and add the DLLs to a 3rd Party Libs directory for reference.

1. Open the previous solution you created in kata 3.
2. Add a reference to RhinoMocks.DLL to the library "Kata.Services.Tests.Unit".
3. Use RhinoMocks to mock the following interfaces (use Resharper to generate the new ones).
NOTE Your mocking levels are stub, dynamic, and strict. The 3rd choice strictly enforces the test specfiications. Start with a strict implementation for now.
  • IInvoiceRepository
  • IInventoryRepository
  • IUnitOfWorkFactory
  • IUnitOfWork


private MockRepository _mockRepository;
private IInvoiceRepository _invoiceRepository;
private IInventoryRepository _inventoryRepository;
private IUnitOfWorkFactory _unitOfWorkFactory;
private IUnitOfWork _unitOfWork;

[SetUp]
public void SetUp()
{
    _mockRepository = new MockRepository();
    _invoiceRepository = _mockRepository.StrictMock();
    _inventoryRepository = _mockRepository.StrictMock();
    _unitOfWorkFactory = _mockRepository.StrictMock();
    _unitOfWork = _mockRepository.StrictMock();
}

4. Create a test.
5. Enter code comments, and basic Rhino Mocks method calls, to generate a test skeleton:

[Test]
public void CreateSimpleInvoiceMethod_ProductCodeAndSerialNumberInputs_GenratesSimpleInvoice()
{
    // declare constants

    // expectations
 
    _mockRepository.ReplayAll();.
    // call to new service method
    _mockRepository.VerifyAll();
}


Now populate the test skeleton as follows:
6. In declare constants, create constants for productCode and serialNumber
7. In declare constants, build an Inventory instance using method StockItemBy()
8. In declare constants, create an Invoice
9. RhinoMocks tests based on object equality, so make sure you have assigned Ids to all your objects.

// declare constants
const string productCode = "ABCD1234";
const string serialNumber = "BB2135315";
var inventory = new Inventory { Id = 1234 };
inventory.StockItemBy(productCode, serialNumber);
var invoice = new Invoice() { Id = 1234 };

10. In expectations, expect that IUnitOfWorkFactory creates IUnitOfWork.
NOTE   If the Create() method exists on the implementation class (UnitOfWorkFactory) but not on the interface, use Resharper to generate it on the interface.
11. Expect that InventoryRepository.LoadInventoryByProduct(IUnitOfWork uow, string productCode) returns Inventory instance.
12. Add comment: // Call to Inventory.PullItemBy(productCode)
13. Add comment: // Call to Invoice.BillItem(item)
NOTE   These must be comments only as they aren't on mock objects. Actual calls would reduce inventory to zero in no context and cause a null error below.
14. Expect that InvoiceRepository.Save(IUnitOfWork uow, Invoice invoice) saves invoice.
15. Expect that IUnitOfWork.Commit() is called
NOTE   If the Commit() method exists on the implementation class (UnitOfWork) but not on the interface, use Resharper to generate it on the interface.
16. Expect that IUnitOfWork.Dispose() is called

// expectations
Expect.Call(_unitOfWorkFactory.Create()).Return(_unitOfWork);
Expect.Call(_inventoryRepository.LoadInventoryByProduct(_unitOfWork, productCode)).Return(inventory);
// Call to Inventory.PullItemBy(productCode)
// Call to Invoice.BillItem(item)
_invoiceRepository.Save(_unitOfWork, invoice);
_unitOfWork.Commit();
_unitOfWork.Dispose();

17. Between ReplayAll and VerifyAll, create InvoicingService instance with all mocked interfaces.

_mockRepository.ReplayAll();

var sut = new InvoicingService(_unitOfWorkFactory, _inventoryRepository, _invoiceRepository);
Invoice actualInvoice = sut.CreateSimpleInvoice(productCode, serialNumber);

_mockRepository.VerifyAll();

18. Now use Resharper to generate the method under test: InvoicingService.CreateSimpleInvoice(productCode,serialNumber).
19. Run the test and watch it fail.
20. Use the expectations set in the test to assemble the method.
21. Remember to wrap the call in IUnitOfWork using statement, and to commit at end of the block

public Invoice CreateSimpleInvoice(string productCode, string serialNumber)
{
    using(IUnitOfWork unitOfWork = _unitOfWorkFactory.Create())
    {
        Inventory inventory = _inventoryRepository.LoadInventoryByProduct(unitOfWork, productCode);
        Item item = inventory.PullItemBy(productCode);
        var invoice = new Invoice();
        invoice.BillItem(item);
        _invoiceRepository.Save(unitOfWork, invoice);
        unitOfWork.Commit();
        return invoice;
    }
}

22. Invoice will fail because its Id cannot be known, so MODIFY the expectation for InvoiceRepository.Save() by adding:
            LastCall.IgnoreArguments();
23. All tests should now pass.

This completes DDD kata part 3.

The next kata will introduce Fluent NHibernate as an implementation framework against the domain entities and repository interfaces that you have created so far.

DDD Kata, Part 3 (build atomic transaction manager i.e. UnitOfWork)

Pre-requisite: DDD Kata Part 2

Kata Focus
1) Work occurs in the Repository layer, which will be used to persist to and from a data store. The data store will be encapsulated behind interfaces.
2) A pre-requisite activity is to build a wrapper interface to encapsulate transaction commit/rollback, with commit and rollback occurring on Dispose().

Completed kata example on github: DDD Kata Part 3 sample code (github)

The Kata
Time goal: under 30 minutes

Repository layer
1. Create new class libraries:
  • Kata.Repository.Tests.Unit
  • Kata.Repository
2. Add a reference to the NUnit.Framework.dll in the new test library.

We will start by creating the interface to wrap transaction commits and rollbacks. For an initial, simple name, we'll use AtomicTransactionManager. In a few minutes we will refactor that to use the name of the corresponding design pattern.

Repository: AtomicTransactionManager
1. In the new Repository unit test library, create class AtomicTransactionManagerTests.cs
2. Verify that AtomicTransactionManager is instance of IAtomicTransactionManager.
3. Verify that the constructor of AtomicTransactionManager sets TransactionState property to “Is Begun”.
NOTE   You should be using Resharper's "generate-by-usage" (alt-Enter) to generate these properties and methods of the sut. However, make sure that the declared type on the sut is interface, otherwise your generate-by-usage will create class-only properties and methods. It should be creating the properties and methods on the interface.
4. Verify that Commit() method sets TransactionState property to “CommitRequested”
The actual name for this design pattern is UnitOfWork. You can read about it here: Martin Fowler, PEAA: Unit of Work
5. Refactor the class and interface you have created so far to UnitOfWork and IUnitOfWork
6. Verify that IUnitOfWork is instance of IDisposable
7. Verify that the Dispose() method sets TransactionState property to “RolledBack”.
8. Verify that calling first the Commit() method, then the Dispose() method, sets TransactionState Property to “Committed”.

UnitOfWorkFactory
Use a factory class to encapsulate the generation of the IUnitOfWork.
9. Verify that UnitOfWorkFactory is instance of IUnitOfWorkFactory.
10. Verify that IUnitOfWorkFactory.Create() returns an IUnitOfWork instance.

Part 3 of the kata is complete.

In the next kata, we will build the service layer with repository interfaces and mock objects.

Continue with DDD Kata Part 4