Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Tuesday, 16 August 2011

Testing the repository and the ORM.

Code Snippet
namespace OSIM.IntegrationTests.OSIM.Core.Persistence {
    // using the Unit Test project to inherit off Specification, which inherits off NBehave.Spec.NUnit
    public class when_using_the_item_type_repository : Specification {
        protected IItemTypeRepository _itemTypeRepository;
        protected StandardKernel _kernel;

        protected override void Establish_context() {
            base.Establish_context();
            _kernel = new StandardKernel(new IntegrationTestModule());
            _itemTypeRepository = _kernel.Get<IItemTypeRepository>();
        }
    }

    public class and_attempting_to_save_and_read_a_value_from_the_datastore : when_using_the_item_type_repository {
        private ItemType _expected;
        private ItemType _result;

        protected override void Establish_context() {
            base.Establish_context();
            // creates different data each time
            // if for some reason old data doesn't get cleared out.
            _expected = new ItemType { Name = Guid.NewGuid().ToString() };
        }

        protected override void Because_of() {
            var itemTypeId = _itemTypeRepository.Save(_expected);
            _result = _itemTypeRepository.GetById(itemTypeId);
        }

        [Test]
        public void then_the_item_type_saved_to_the_database_should_equal_the_item_type_retrieved() {
            _result.Id.ShouldEqual(_expected.Id);
            _result.Name.ShouldEqual(_expected.Name);
        }
    }
}

asdf

Code Snippet
<configuration>
  <appSettings>
    <add key="localDb" value="Data Source=SSDLAPTOP; Initial Catalog=OSIM.Dev; Integrated Security=True"/>
  </appSettings>
</configuration>

Every time the test runs, it recreates the db:

image

asdf

image

asdf

Code Snippet
namespace OSIM.IntegrationTests {
    public class IntegrationTestModule : NinjectModule {
        public override void Load() {
            // when ninject is asked for an instance of IItemTypeRepository
            // return ItemTypeRepository
            Bind<IItemTypeRepository>().To<ItemTypeRepository>();

            Bind<ISessionFactory>().ToProvider
                (new IntegrationTestSesssionFactoryProvider());
        }
    }

    public class IntegrationTestSesssionFactoryProvider : Provider<ISessionFactory> {

        protected override ISessionFactory CreateInstance(IContext context) {
            var sessionFactory = Fluently.Configure()
                                    .Database(MsSqlConfiguration.MsSql2008
                                        .ConnectionString(c => c.Is(ConfigurationManager.AppSettings["localDb"])).ShowSql())
                                        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<ItemTypeMap>()
                                            .ExportTo(@"e:\temp"))
                                        .ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
                                        .BuildSessionFactory();
            return sessionFactory;
        }
    }
}

Wiring up FNH using ninject.

| | # 

Business owner must choose the first stories to be developed in the first iteration.

“A user should be able to add a new type of item to the application”

Features:

  • An item type entity and a persistence layer
  • An item type domain service that can provide a list of item types in the data store
  • A user interface to enable business users to list existing item types and create new ones

Inside out / outside in… we are doing the former ie starting with the Repository layer.

http://nbehave.codeplex.com/releases/view/68223

Code Snippet
public class when_working_with_the_item_type_repository : Specification {
    }

    public class and_saving_a_valid_item_type : when_working_with_the_item_type_repository {
        private int _result;
        private IItemTypeRepository _itemTypeRepository;
        private ItemType _testItemType;
        private int _itemTypeId;

        protected override void Because_of() {
            _result = _itemTypeRepository.Save(_testItemType);
        }
        
        protected override void Establish_context() {
            base.Establish_context();

            var randomNumberGenerator = new Random();
            _itemTypeId = randomNumberGenerator.Next(32000);

            // making a mock ISessionFactory
            // which just returns the random number
            // when an ItemType is passed in and saved
            var sessionFactory = new Mock<ISessionFactory>();
            var session = new Mock<ISession>();
            session.Setup(s => s.Save(_testItemType))
                            .Returns(_itemTypeId);

            sessionFactory.Setup(sf => sf.OpenSession())
                            .Returns(session.Object);

            // injecting in our mock sessionFactory
            _itemTypeRepository = new ItemTypeRepository(sessionFactory.Object);
        }

        [Test]
        public void then_a_valid_item_type_id_should_be_returned() {
            _result.ShouldEqual(_itemTypeId);
        }
    }
Specification inherits off SpecBase which is NBehave.Spec.Nunit.    So basically Nunit with BDD style sugar.

Using Moq to Mock out the ORM (Fluent NHibernate).

Code Snippet
public interface IItemTypeRepository {
        int Save(ItemType _testItemType);
    }

    public class ItemTypeRepository : IItemTypeRepository {
        private ISessionFactory _sessionFactory;

        public ItemTypeRepository(ISessionFactory sessionFactory) {
            _sessionFactory = sessionFactory;
        }

        public int Save(ItemType itemType) {
            int id;
            using (var session = _sessionFactory.OpenSession()) {
                id = (int)session.Save(itemType);
                session.Flush();
            }
            return id;
        }
    }

Second test and Refactoring

Code Snippet
public class when_working_with_the_item_type_repository : Specification {
        protected IItemTypeRepository _itemTypeRepository;
        protected Mock<ISessionFactory> _sessionFactory;
        // protected so can restub in each test the required behaviour
        protected Mock<ISession> _session;

        protected override void Establish_context() {
            base.Establish_context();
            // Mock out FNH
            _sessionFactory = new Mock<ISessionFactory>();
            _session = new Mock<ISession>();

            _sessionFactory.Setup(sf => sf.OpenSession())
                            .Returns(_session.Object);

            _itemTypeRepository = new ItemTypeRepository(_sessionFactory.Object);
        }
    }

    // second test
    public class and_saving_an_invalid_item_type : when_working_with_the_item_type_repository {
        private Exception _result;

        protected override void Because_of() {
            try {
                _itemTypeRepository.Save(null);
            }
            catch (Exception exception) {
                _result = exception;
            }
        }

        protected override void Establish_context() {
            base.Establish_context();
            // the mock knows that when a null is passed
            // instead of an ItemType then throw ArgumentNullException
            _session.Setup(s => s.Save(null))
                            .Throws(new ArgumentNullException());
        }

        [Test]
        public void then_an_argument_null_exception_should_be_raised() {
            _result.ShouldBeInstanceOfType(typeof(ArgumentNullException));
        }
    }

    // first test
    public class and_saving_a_valid_item_type : when_working_with_the_item_type_repository {
        private int _result;
        private ItemType _testItemType;
        private int _itemTypeId;

        protected override void Because_of() {
            _result = _itemTypeRepository.Save(_testItemType);
        }
        
        protected override void Establish_context() {
            base.Establish_context();

            var randomNumberGenerator = new Random();
            _itemTypeId = randomNumberGenerator.Next(32000);

            // when passed an ItemType, return the random number
            _session.Setup(s => s.Save(_testItemType))
                            .Returns(_itemTypeId);
        }

        [Test]
        public void then_a_valid_item_type_id_should_be_returned() {
            _result.ShouldEqual(_itemTypeId);
        }
    }

Now have 2 unit tests.. which are testing the repository

  • Saving a valid item type returns newly created id
  • Saving an invalid item type throws an ArgumentNullException

The repository is being tested using Mocks of the FNH Save method.  Because we’re using FNH’s interfaces it should just work (after putting in config files and creating the DB!).

| | # 

/dev/osim/src

/dev/osim/libs – 3rd party dlls

Created a blank solution first, then added other projects with correct names.

image

ExternalServices is a WCF project, Web is MVC3 and Win is WPF.

Source is using VisualSVNServer  / TortoiseSVN

image

| | # 
# Monday, 15 August 2011

an Entity could be a Person object.

Code Snippet
// app is comprised of various services
    // which have entities (components)

    public class BusinessService {
        private readonly string _databaseConnectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
        private readonly string _webServiceAddress = ConfigurationManager.AppSettings["MyWebServiceAddress"];
        private readonly LoggingDataSink _loggingDataSink;
    
        private DataAccessComponent _dataAccessComponenet;
        private WebServiceProxy _webServiceProxy;
        private LoggingComponent _loggingComponent;

        public BusinessService() {
            _loggingDataSink = new LoggingDataSink();
            _loggingComponent = new LoggingComponent(_loggingDataSink);
            _webServiceProxy = new WebServiceProxy(_webServiceAddress);
            _dataAccessComponenet = new DataAccessComponent(_databaseConnectionString);
        }
    }

refactoring for constructor based DI:

Code Snippet
    public class BusinessServiceWithDI {
        private IDataAccessComponent _dataAccessComponent;
        private IWebServiceProxy _webServiceProxy;
        private ILoggingComponent _loggingComponent;

        public BusinessServiceWithDI(IDataAccessComponent dataAccessComponent, IWebServiceProxy webServiceProxy, ILoggingComponent loggingComponent) {
            _dataAccessComponent = dataAccessComponent;
            _webServiceProxy = webServiceProxy;
            _loggingComponent = loggingComponent;
        }
    }

Can now inject whatever I like as long as it implements the required interface eg a ‘test’ database.  So mock instances of these services can be injected for testing.

DI frameworks give us an alternative to Factory Patterns which can get unwieldy.

Allow us to easily define dependencies and rules for creating the concrete objects.

Ninject

Code Snippet
public class BusinessService {
        private IDataAccessComponent _dataAccessComponent;
        private IWebServiceProxy _webServiceProxy;
        private ILoggingComponent _loggingComponent;

        public BusinessService(IDataAccessComponent dataAccessComponent, IWebServiceProxy webServiceProxy, ILoggingComponent loggingComponent) {
            _dataAccessComponent = dataAccessComponent;
            _webServiceProxy = webServiceProxy;
            _loggingComponent = loggingComponent;
        }
    }

then:

Code Snippet
[Test]
        public void ShouldBeAbleToGetBusinessServiceFromNinject() {
            BusinessService actual;
            var kernel = new StandardKernel(new CoreModule());
            actual = kernel.Get<BusinessService>();
            Assert.IsNotNull(actual);
        }

so can get a BusinessService and all of its dependencies injected for us.

Code Snippet
public class CoreModule : NinjectModule{
        public override void Load() {
            // any requests to ninject for a class that implements ILoggingDataSink should return
            // a concrete instance of LoggingDataSink
            Bind<ILoggingDataSink>().To<LoggingDataSink>();
            Bind<ILoggingComponent>().To<LoggingComponent>();
            Bind<IDataAccessComponent>().ToProvider(new DataAccessComponentProvider());
            Bind<IWebServiceProxy>().ToProvider(new WebServiceProxyComponentProvider());
        }
    }

    public class DataAccessComponentProvider : Provider<IDataAccessComponent> {
        protected override IDataAccessComponent CreateInstance(IContext context) {
            var databaseConnectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
            return new DataAccessComponent(databaseConnectionString);
        }
    }

    public class WebServiceProxyComponentProvider : Provider<IWebServiceProxy> {
        protected override IWebServiceProxy CreateInstance(IContext context) {
            var webServiceAddress = ConfigurationManager.AppSettings["MyWebServiceAddress"];
            return new WebServiceProxy(webServiceAddress);
        }
    }

Service and Repository

Code Snippet
public interface IPersonService {
        Person GetPerson(int personId);
    }

    public class PersonService : IPersonService {
        private readonly IPersonRepository _personRepository;

        public PersonService(IPersonRepository personRepository) {
            _personRepository = personRepository;
        }
        public Person GetPerson(int personId) {
            return _personRepository.GetPerson(personId);
        }
    }

    public class Person {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public interface IPersonRepository {
        Person GetPerson(int personId);
    }

    public class PersonRepository : IPersonRepository {
        private readonly IList<Person> _personList;

        public PersonRepository() {
            _personList = new List<Person> {
                                            new Person{Id = 1, FirstName = "John", LastName="Doe"},
                                            new Person{Id = 2, FirstName = "Richard", LastName="Roe"},
                                            new Person{Id = 3, FirstName = "Amy", LastName="Adams"}
                                            };
        }

        public Person GetPerson(int personId) {
            var person = _personList.Where(p => p.Id == personId).FirstOrDefault();
            return person;
        }
    }

tests:

Code Snippet
[TestFixture]
    public class PersonServiceTests {
        [Test]
        // not truly a unit test as it breaks boundaries between PersonService and PersonRepository
        // we should pass a mock repository into the service.
        public void ShouldBeAbleToCallPersonServiceAndGetPerson() {
            var expected = new Person { Id = 1, FirstName = "John", LastName = "Doe" };
            var kernel = new StandardKernel(new CoreModule());
            var personService = kernel.Get<PersonService>();
            var actual = personService.GetPerson(expected.Id);

            Assert.AreEqual(expected.Id, actual.Id);
            Assert.AreEqual(expected.FirstName, actual.FirstName);
            Assert.AreEqual(expected.LastName, actual.LastName);
        }

        [Test]
        // not using ninject
        // using moq
        public void ShouldBeAbleToCallPersonServiceAndGetPersonWithMock() {
            var expected = new Person { Id = 1, FirstName = "Bob", LastName = "Smith" };
            var personRepositoryMock = new Mock<IPersonRepository>();
            personRepositoryMock
                    .Setup(pr => pr.GetPerson(1))
                    .Returns(new Person { Id = 1, FirstName = "Bob", LastName = "Smith" });
            var personService = new PersonService(personRepositoryMock.Object);

            var actual = personService.GetPerson(expected.Id);

            Assert.AreEqual(expected.Id, actual.Id);
            Assert.AreEqual(expected.FirstName, actual.FirstName);
            Assert.AreEqual(expected.LastName, actual.LastName);
        }
    }
| | # 

Act of changing internal implementation of a class or method with aim of making it more readable and maintainable.

YAGNI – You aren’t going to need it

OOP Principles

  • Encapsulation
  • Inheritance.. Is a
  • Polymorphism – more than 1 form.. in C# we use Interfaces

Is a.. Has a..  

Favour Composition over inheritance

SOLID Principles

Single Responsibility Principle – method should do only 1 thing.

Open / Closed Principle – open for extension, closed for modification.  Closely related to Inheritance.  eg Base class which is closed for modification, but can be extended by overriding.

Liskov Substitution Principle – Design by contract.

Interface Segregation Principle

Dependency Inversion Principle

Code Smells (Antipatterns)

Duplicate Code / Similar Classes eg doing same calculation in different methods

Big Classes / Methods and regions in classes bad too.. rather have many smaller classes

Comments – dont need.  Well written code should be easy to follow.  Use source control to see who did what.

Bad Names

Feature Envy

Too Much If/Switch

Try/Catch Bloat

Typical Refactoring

Extracting Classes or Interfaces

Code Snippet
    public class Invoice {
    }

    public class Customer {
    }

    public class InvoiceService {
        public string CreateInvoice(Invoice invoice) {
            return "a";
        }
        public string ProcessPayment(Invoice invoice, Double amount) {
            return "a";
        }
        public double GetAmountOwed(Invoice invoice) {
            return 1;
        }
        public double GetTotalAmountInvoicedLastFY(Customer customer) {
            return 1;
        }
        public double GetTotalAmountPaidLastFY(Customer customer) {
            return 1;
        }
    }

Extracted out interfaces, so implementation only gets to see methods it should do:

Code Snippet
public class Invoice {
    }

    public class Customer {
    }

    public interface IInvoiceCreatingService {
        string CreateInvoice(Invoice invoice);
    }

    public interface IInvoicePaymentService {
        string ProcessPayment(Invoice invoice, Double amount);
        double GetAmountOwed(Invoice invoice);
    }

    public interface IInvoiceReportingService {
        double GetTotalAmountInvoicedLastFY(Customer customer);
        double GetTotalAmountPaidLastFY(Customer customer);
    }

    public class InvoiceService : IInvoiceCreatingService, IInvoicePaymentService, IInvoiceReportingService {
        public string CreateInvoice(Invoice invoice) {
            return "a";
        }
        public string ProcessPayment(Invoice invoice, Double amount) {
            return "a";
        }
        public double GetAmountOwed(Invoice invoice) {
            return 1;
        }
        public double GetTotalAmountInvoicedLastFY(Customer customer) {
            return 1;
        }
        public double GetTotalAmountPaidLastFY(Customer customer) {
            return 1;
        }
    }

    public class TestInvoicePaymentClass {
        public string DoinvoicePayments() {
            IInvoicePaymentService invoiceService = new InvoiceService();
            invoiceService.ProcessPayment(new Invoice(), 1);
            return "a";
        }
    }

Extract Methods

Some code to refactor:

Code Snippet
public class CustomerAddress {
        public string State;
    }
    public class Invoice {
        public string InvoiceNumber;
        public double TotalPrice;
        public int Quantity;
        public string CustomerName;
        public CustomerAddress CustomerAddress;
        public string CustomerBillingInformation;

        public bool Approved { get; set; }
    }
    public class Customer {
        public string CustomerName;
        public CustomerAddress CustomerAddress;
        public string CustomerBillingInformation;
    }

    public class CustomerService {
        public Customer GetCustomer(string customerNumber) {
            return new Customer();
        }
    }

    public class PaymentProcessingService {
        public string ProcessPayment(double totalPrice, string customerBillingInformation) {
            var paymentAuthorizationCode = "a";
            return paymentAuthorizationCode;
        }
    }

    public class InvoiceService {
        public void Post(Invoice invoice) {
        }


        public class WidgetService {
            private const double PricePerWidget = 1.5;
            CustomerService _customerService = new CustomerService();
            PaymentProcessingService _paymentProcessingService = new PaymentProcessingService();
            InvoiceService _invoiceService = new InvoiceService();

            public string PlaceOrderForWidgets(int quantity, string customerNumber) {
                var invoice = new Invoice {
                    InvoiceNumber = Guid.NewGuid().ToString(),
                    TotalPrice = PricePerWidget * quantity,
                    Quantity = quantity
                };

                var customer = _customerService.GetCustomer(customerNumber);
                invoice.CustomerName = customer.CustomerName;
                invoice.CustomerAddress = customer.CustomerAddress;
                invoice.CustomerBillingInformation = customer.CustomerBillingInformation;

                double tax;
                switch (invoice.CustomerAddress.State.ToUpper()) {
                    case "OH":
                        tax = invoice.TotalPrice * .15;
                        break;
                    case "MI":
                        tax = invoice.TotalPrice * .22;
                        break;
                    case "NV":
                        tax = invoice.TotalPrice * .05;
                        break;
                    default:
                        tax = 0.0;
                        break;
                }

                var shippingPrice = invoice.TotalPrice * .1;
                invoice.TotalPrice += shippingPrice;
                invoice.TotalPrice += tax;

                var paymentAuthorizationCode = _paymentProcessingService.ProcessPayment(invoice.TotalPrice,
                                                                                        customer.CustomerBillingInformation);
                invoice.Approved = !string.IsNullOrEmpty(paymentAuthorizationCode);
                _invoiceService.Post(invoice);
                return "a";
            }
        }


    }

This does 5 different tasks:

  • creates an invoice
  • associates the invoice with a customer
  • determines tax based on the customers state
  • determines shipping costs
  • authorizes payment

So 5 different reasons this method may have to change (breaks SRP)

Rename Variables, Fields, Methods and Classes

Properties and Fields are information an object contains.  Can have get and set procedures on them

Code Snippet
public class SampleClass {
        public int SampleProperty { get; private set; } // property, field or public member variable.. auto implemented property
        int _privateVariable; // class level private and protected variable

        public int sampleMethod(string sampleParam) {
            string procedureLevelVariable = "";
            return 1;
        }
    }
| | # 
# Friday, 12 August 2011

Mock objects are designed to stand in.. allow us to test code without having to worry about consequences

  • Dummy – return a predefined response, can’t vary response based on input parameters
  • Fake
  • Stub
  • Mock

Dummy

Code Snippet
class DummyDependency : IDependency {
        public int GetValue(string s) {
            return 1;
        }
    }

    [TestFixture]
    public class InitialTests {

        [Test]
        public void TestWithADummy() {
            var dependency = new DummyDependency();
            var dependentClass = new DependentClass(dependency);
            const string param = "abc";
            const int expectedResultOne = 1;

            var resultOne = dependentClass.GetValue(param);
            Assert.AreEqual(expectedResultOne, resultOne);
        }
    }

constructor based dependency injection:

Code Snippet
    public interface IDependency {
        int GetValue(string s);
    }

    public class DependentClass : IDependency {
        private readonly IDependency _dependency;

        public DependentClass(IDependency dependency) {
            _dependency = dependency;
        }

        public int GetValue(string s) {
            return _dependency.GetValue(s);
        }
    }

Fakes and Stubs

Code Snippet
[Test]
        // a fake is a similar thing
        public void TestWithAStub() {
            var dependency = new StubDependency();
            var dependentClass = new DependentClass(dependency);
            const string param1 = "abc";
            const string param2 = "xyz";

            const int expectedResultOne = 1;
            const int expectedResultTwo = 2;

            var resultOne = dependentClass.GetValue(param1);
            var resultTwo = dependentClass.GetValue(param2);

            Assert.AreEqual(expectedResultOne, resultOne);
            Assert.AreEqual(expectedResultTwo, resultTwo);
        }

 

Code Snippet
class StubDependency : IDependency {
        public int GetValue(string s) {
            if (s == "abc")
                return 1;
            if (s == "xyz")
                return 2;
            return 0;
        }
    }

Mocks

More complex and can contain state.

Moq

Testing a concrete implementation here, which will take 30s!

Code Snippet
    public interface ILongRunningLibrary {
        string RunForALongTime(int interval);
    }

    public class LongRunningLibrary : ILongRunningLibrary {
        public string RunForALongTime(int interval) {
            var timeToWait = interval * 1000;
            Thread.Sleep(timeToWait);
            return string.Format("Waited {0} seconds", interval);
        }
    }

    [TestFixture]
    public class MoqExamples {
        private ILongRunningLibrary _longRunningLibrary;
        [SetUp]
        public void SetupForTest() {
            _longRunningLibrary = new LongRunningLibrary();
        }

        [Test]
        public void TestLongRunningLibrary() {
            const int interval = 30;
            var result = _longRunningLibrary.RunForALongTime(interval);
            Debug.WriteLine("Return from method was a '{0}'", result);
        }
    }

And now using Moq:

Code Snippet
public interface ILongRunningLibrary {
        string RunForALongTime(int interval);
    }

    public class LongRunningLibrary : ILongRunningLibrary {
        public string RunForALongTime(int interval) {
            var timeToWait = interval * 1000;
            Thread.Sleep(timeToWait);
            return string.Format("Waited {0} seconds", interval);
        }
    }

    [TestFixture]
    public class MoqExamples {
        private Mock<ILongRunningLibrary> _longRunningLibrary;
        [SetUp]
        public void SetupForTest() {
            _longRunningLibrary = new Mock<ILongRunningLibrary>();
        }

        [Test]
        public void TestLongRunningLibrary() {
            const int interval = 30;
            //_longRunningLibrary.Setup(lrl => lrl.RunForALongTime(30))
            //.Returns("This method has been mocked!");
            _longRunningLibrary.Setup(lrl => lrl.RunForALongTime(It.IsAny<int>()))
                                .Returns((int s) =>
                                    string.Format(
                                        "This method has been mocked!" +
                                        "The input value was {0}", s));
            _longRunningLibrary
                            .Setup(lrl => lrl.RunForALongTime(0))
                            .Throws(new ArgumentException("0 is not a valid interval"));

            var result = _longRunningLibrary.Object.RunForALongTime(interval);
            Debug.WriteLine(result);
        }

        [Test]
        public void TestLongRunningLibraryFailsWhenZeroIsPassedIn() {
            const int interval = 0;
            //_longRunningLibrary.Setup(lrl => lrl.RunForALongTime(30))
                                //.Returns("This method has been mocked!");
            _longRunningLibrary.Setup(lrl => lrl.RunForALongTime(It.IsAny<int>()))
                                .Returns((int s) =>
                                    string.Format(
                                        "This method has been mocked!" +
                                        "The input value was {0}", s));
            _longRunningLibrary
                            .Setup(lrl => lrl.RunForALongTime(0))
                            .Throws(new ArgumentException("0 is not a valid interval"));
                                
            var result = _longRunningLibrary.Object.RunForALongTime(interval);
            Debug.WriteLine(result);
        }
    }
| | # 
# Thursday, 11 August 2011

Successful teams – always learning new tools and techniques, with the aim of developing software faster and with fewer bugs.

Agile Manifesto

  • Individuals and interactions over processes and tools
  • Working software over comprehensive documentation
  • Customer collaboration over contract negotiation
  • Responding to change over following a plan

Write the test first, then the class

Code Snippet
[Test]
        public void ShouldFindOneYInMysterious() {
            var stringToCheck = "mysterious";
            var stringToFind = "y";
            var expectedResult = 1;
            var classUnderTest = new StringUtilities();

            int actualResult = classUnderTest.CountOccurences(stringToCheck, stringToFind);

            Assert.AreEqual(expectedResult, actualResult);
        }

        [Test]
        public void ShouldFindTwoSInMysterious() {
            var stringToCheck = "mysterious";
            var stringToFind = "s";
            var expectedResult = 2;
            var classUnderTest = new StringUtilities();

            int actualResult = classUnderTest.CountOccurences(stringToCheck, stringToFind);

            Assert.AreEqual(expectedResult, actualResult);
        }

        [Test]
        public void SearchShouldBeCaseInSensitive() {
            var stringToCheck = "mySterious";
            var stringToFind = "s";
            var expectedResult = 2;
            var classUnderTest = new StringUtilities();

            int actualResult = classUnderTest.CountOccurences(stringToCheck, stringToFind);

            Assert.AreEqual(expectedResult, actualResult);
        }

        [Test]
        public void ShouldBeAbleToHandleNulls() {
            string stringToCheck = null;
            var stringToFind = "s";
            var expectedResult = -1;
            var classUnderTest = new StringUtilities();

            int actualResult = classUnderTest.CountOccurences(stringToCheck, stringToFind);

            Assert.AreEqual(expectedResult, actualResult);
        }

 

Code Snippet
public class StringUtilities {
        public int CountOccurences(string stringToCheck, string stringToFind) {
            if (stringToCheck == null) return -1;

            var stringAsCharArray = stringToCheck.ToUpper().ToCharArray();
            var stringToCheckForAsChar = stringToFind.ToUpper().ToCharArray()[0];
            var occuranceCount = 0;

            for (var characterIndex = 0; characterIndex <= stringAsCharArray.GetUpperBound(0); characterIndex++) {
                if (stringAsCharArray[characterIndex] == stringToCheckForAsChar)
                    occuranceCount++;
            }

            return occuranceCount;
        }
    }
| | #