S#arp Architecture

  1. Go to Northwind.Tests/Northwind.Core and add a new tests class called StaffMemberTests.cs with an initial test of CanCreateStaffMember(). (Note that the test is written as a question.) The class should look as follows:

    using NUnit.Framework;
    using NUnit.Framework.SyntaxHelpers;  // not needed for at least NUnit 2.5.2 and greater
    using Northwind.Core; 
    namespace Tests.Northwind.Core
    {
        [TestFixture]    
        public class StaffMemberTests
        {
            [Test]        
            public void CanCreateStaffMember() {
                string employeeNumber = "ABC123";
                string firstName = "Karel";
                string lastName = "Čapek"; 
                StaffMember staffMember =
                    new StaffMember(employeeNumber) {
                        FirstName = firstName,
                        LastName = lastName
                    }; 
    
                Assert.That(staffMember.EmployeeNumber,Is.EqualTo(employeeNumber));
                Assert.That(staffMember.FirstName, Is.EqualTo(firstName));
                Assert.That(staffMember.LastName, Is.EqualTo(lastName));
            }
        }
    }
    

    Note that the constructor of StaffMember only takes an employee number. This is the minimal amount of information to create a valid, unique staff member, as specified by the requirements.


  2. Compile the build and notice that it breaks due to the missing StaffMember class.


  3. Go to Northwind.Core and add a StaffMember.cs class file to develop the StaffMember domain object, as follows: (Note that we’ve only added just enough code to get the test to compile.)

    namespace Northwind.Core
    {
        public class StaffMember
        {
            public StaffMember(string employeeNumber) {} 
            public string EmployeeNumber { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
        }
    }
    


  4. Open NUnit and load the tests project by going to File / Open Project and open Northwind.Tests/bin/Debug/Northwind.Tests.dll. Double click the CanCreateStaffMember test to have it run. You should see it fail because EmployeeNumber is null.


  5. Go back to the StaffMember domain object and alter the constructor as follows:

    public StaffMember(string employeeNumber) {
        EmployeeNumber = employeeNumber;
    }
    

  6. Compile and run the test and again to see it go green…woohoo!


  7. Time to refactor! In the constructor of StaffMember, it’s possible to set the employeeNumber parameter to a null or empty string object. This is bad. What we’d like to do is enforce that a valid employee number is provided. Let’s use the design-by-contract utility to enforce this with a Check.Require. This is good. Furthermore, to protect the employee number in the future, since it shouldn’t change, let’s protect the setter of EmployeeNumber. Be sure to run the unit tests again to make sure nothing broke while refactoring. When implementing this refactoring, a test driven approach should be followed, as was performed in the previous six steps. For brevity, the unit test below demonstrates step one of the refactoring process followed by code which gets the test to pass in step six of the process. (Note that we can’t unit test proving that the EmployeeNumber’s setter is protected as it will not compile if we attempt to set it.) So to complete this step, add the following new test to the StaffMemberTests class:

    using SharpArch.Core; 
    
    ...
    
    [Test]
    [ExpectedException(typeof(PreconditionException))]
    public void CannotCreateStaffMemberWithInvalidEmployeeId() {
        new StaffMember("  ");
    }
    

    Then get the test passing by altering StaffMember to reflect the following:

    using SharpArch.Core;
    using System; 
    namespace Northwind.Core
    {
        public class StaffMember
        {
            public StaffMember(string employeeNumber) {
                Check.Require(!string.IsNullOrEmpty(employeeNumber)
                    && employeeNumber.Trim() != String.Empty,
                    "employeeNumber must be provided"); 
                EmployeeNumber = employeeNumber;
            } 
    
            public string EmployeeNumber { get; protected set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
        }
    }
    



ScrewTurn Wiki version 2.0.36. Some of the icons created by FamFamFam.