Welcome to EMC Consulting Blogs Sign in | Join | Help

Owain Wraggs' Blog

I have now left EMC Consulting, you can subscribe to my new blog here: http://blog.endjin.com/author/owain-wragg/

  • AutoMapper Mapping from Multiple Objects

    When using AutoMapper (http://automapper.codeplex.com ) I often have a scenario where I need to map several entities into one entity. Commonly this occurs when mapping from a number domain entities into a single view model (ASP.NET MVC). Unfortunately the AutoMapper API does not expose functionality to map several entities into one entity; however it is relatively simple to create some helper method to do this. Below I will illustrate the approach that I have taken.

    In this example I have the following entities in my domain model

        public class Person

        {

            public int Id { get; set; }

     

            public string Firstname { get; set; }

     

            public string Surname { get; set; }

        }

     

        public class Address

        {

            public int Id { get; set; }

     

            public string AddressLine1 { get; set; }

     

            public string AddressLine2 { get; set; }

     

            public string Country { get; set; }

        }

     

        public class Comment

        {

            public string Text { get; set; }

     

            public DateTime Created { get; set; }

        }

     

    In addition to this I have a requirement to render the person details the person’s address and any related comment on a single page (using ASP.NET MVC). To implement this I have created the view model shown below, which includes data from all three of the domain entities shown above

        public class PersonViewModel

        {

            public int Id { get; set; }

     

            [DisplayName("Firstname")]

            public string Firstname { get; set; }

     

            [DisplayName("Surname")]

            public string Surname { get; set; }

     

            [DisplayName("Address Line 1")]

            public string AddressLine1 { get; set; }

     

            [DisplayName("Address Line 2")]

            public string AddressLine2 { get; set; }

     

            [DisplayName("Country Of Residence")]

            public string Country { get; set; }

     

            [DisplayName("Admin Comment")]

            public string Comment { get; set; }

     

        }

     

    In the controller action method I make three separate calls into the domain layer to retrieve the required entities but this still leaves the issue that I need to map several source entities onto a single destination entity. To perform this mapping I created a helper class which encapsulates AutoMapper and exposes functionality which enables the mapping of several source objects onto one destination object. This class is shown below

        public static class EntityMapper

        {

            public static T Map<T>(params object[] sources) where T : class

            {

                if (!sources.Any())

                {

                    return default(T);

                }

     

                var initialSource = sources[0];

     

                var mappingResult = Map<T>(initialSource);

     

                // Now map the remaining source objects

                if (sources.Count() > 1)

                {

                    Map(mappingResult, sources.Skip(1).ToArray());

                }

     

                return mappingResult;

            }

     

            private static void Map(object destination, params object[] sources)

            {

                if (!sources.Any())

                {

                    return;

                }

     

                var destinationType = destination.GetType();

     

                foreach (var source in sources)

                {

                    var sourceType = source.GetType();

                    Mapper.Map(source, destination, sourceType, destinationType);

                }

            }

     

            private static T Map<T>(object source) where T : class

            {

                var destinationType = typeof(T);

                var sourceType = source.GetType();

     

                var mappingResult = Mapper.Map(source, sourceType, destinationType);

     

                return mappingResult as T;

            }

        }

     

    To map several source objects onto one destination I have made use of the functionality provided by AutoMapper which allows you to perform a mapping between a source object and a destination object that already exists.

    Finally below is the code from the controller that retrieves the three entities and performs the mapping onto a single view model

            public ActionResult Index()

            {

               

                // Retrieve the person, address and comment entities and

                // map them on to a person view model entity

                var personId = 23;

     

                var person = _personTasks.GetPerson(personId);

                var address = _personTasks.GetAddress(personId);

                var comment = _personTasks.GetComment(personId);

     

                var personViewModel = EntityMapper.Map<PersonViewModel>(person, address, comment);

     

                return this.View(personViewModel);

            }

     

    The solution containing the sample code shown in this post is attached.

  • AutoMapper Profiles

    I’ve now worked on several ASP.NET MVC projects which utilise AutoMapper (http://automapper.codeplex.com/) to perform the mapping between view models and domain objects and vice versa. AutoMapper works brilliantly and I would recommend it to anyone who needs to perform mapping between different objects.

    The approach I’ve always taken when using AutoMapper is to create a mapper class which is responsible for mapping one type to another type. So for example given the two entities below

        public class Address

        {

            public string FirstLine { get; set; }

     

            public string Country { get; set; }

     

            public string PostCode { get; set; }

        }

     

    And

        public class AddressViewModel

        {

            [DisplayName("Address Line One")]

            public string PersonAddressLineOne { get; set; }

     

            [DisplayName("Country Of Residence")]

            public string PersonCountryOfResidence { get; set; }

     

            [DisplayName("Post Code")]

            public string PostCode { get; set; }

        }

     

    If I wanted to map from an Address entity to an AddressViewModel entity I would create an AddressToAddressViewModelMapper class which is responsible for performing the mapping (shown below)

        public class AddressToAddressViewModelMapper : IMapper<Address, AddressViewModel>

        {

            public AddressToAddressViewModelMapper()

            {

                AutoMapper.Mapper.CreateMap<Address, AddressViewModel>()

                    .ForMember(x => x.PersonAddressLineOne, opt => opt.MapFrom(source => source.FirstLine))

                    .ForMember(x => x.PersonCountryOfResidence, opt => opt.MapFrom(source => source.Country));

            }

     

            public AddressViewModel Map(Address source)

            {

                var destination = AutoMapper.Mapper.Map<Address, AddressViewModel>(source);

                return destination;

            }

        }

     

    The issue I have with this approach is that even for a small number of entities you have to create a large number of mapper classes and this bloats your solution and further to this if you are using dependency injection you end up injecting a large number of mappers into each controller increasing the complexity of both the code and any unit tests that you have.

    To illustrate how complex such mappers can get, I will show an example of mapping from a simple domain model to an equally simple view model

    Shown below are the domain objects

        public class Person

        {

            public int Id { get; set; }

     

            public string Firstname { get; set; }

     

            public string Surname { get; set; }

     

            public Address Address { get; set; }

     

            public List<Note> Notes { get; set; }

        }

     

        public class Address

        {

            public string FirstLine { get; set; }

     

            public string Country { get; set; }

     

            public string PostCode { get; set; }

        }

     

        public class Note

        {

            public int Id { get; set; }

     

            public string Text { get; set; }

        }

     

    Which need to be mapped to the following view model objects

        public class PersonViewModel

        {

            [DisplayName("Person Id")]

            public int Id { get; set; }

     

            [DisplayName("Person Firstname")]

            public string Firstname { get; set; }

     

            [DisplayName("Person surname")]

            public string Surname { get; set; }

     

            public AddressViewModel Address { get; set; }

     

            public List<NoteViewModel> Notes { get; set; }

        }

     

        public class AddressViewModel

        {

            [DisplayName("Address Line One")]

            public string PersonAddressLineOne { get; set; }

     

            [DisplayName("Country Of Residence")]

            public string PersonCountryOfResidence { get; set; }

     

            [DisplayName("Post Code")]

            public string PostCode { get; set; }

        }

     

        public class NoteViewModel

        {

            [DisplayName("Note Id")]

            public int Id { get; set; }

     

            [DisplayName("Note Text")]

            public string Text { get; set; }

        }

     

    To perform the mapping we need to create a mapper class for each mapping that is performed, in this example mappers that perform the following mappings are required

    • Person to PersonViewModel
    • Address to AddressViewModel
    • Note to NoteViewModel

    The mapping classes are shown below, note that when performing a mapping from a Person domain object the mapper responsible for performing the mapping will need to be aware of the mappers for the other complex types that the Person domain object contains (Address and Note)

        public class PersonToPersonViewModelMapper : IMapper<Person, PersonViewModel>

        {

            private NoteToNoteViewModelMapper _noteToNoteViewModelMapper = new NoteToNoteViewModelMapper();

            private AddressToAddressViewModelMapper _addressToAddressViewModelMapper = new AddressToAddressViewModelMapper();

     

            public PersonToPersonViewModelMapper()

            {

                AutoMapper.Mapper.CreateMap<Person, PersonViewModel>();

            }

     

            public PersonViewModel Map(Person source)

            {

                var destination = AutoMapper.Mapper.Map<Person, PersonViewModel>(source);

     

                destination.Address = source.Address.MapUsing(_addressToAddressViewModelMapper);

     

                destination.Notes = source.Notes.MapAllUsing(_noteToNoteViewModelMapper);

     

                return destination;

            }

        }

     

        public class AddressToAddressViewModelMapper : IMapper<Address, AddressViewModel>

        {

            public AddressToAddressViewModelMapper()

            {

                AutoMapper.Mapper.CreateMap<Address, AddressViewModel>()

                    .ForMember(x => x.PersonAddressLineOne, opt => opt.MapFrom(source => source.FirstLine))

                    .ForMember(x => x.PersonCountryOfResidence, opt => opt.MapFrom(source => source.Country));

            }

     

            public AddressViewModel Map(Address source)

            {

                var destination = AutoMapper.Mapper.Map<Address, AddressViewModel>(source);

                return destination;

            }

        }

     

        public class NoteToNoteViewModelMapper : IMapper<Note, NoteViewModel>

        {

            public NoteToNoteViewModelMapper()

            {

                AutoMapper.Mapper.CreateMap<Note, NoteViewModel>();

            }

     

            public NoteViewModel Map(Note source)

            {

                var destination = AutoMapper.Mapper.Map<Note, NoteViewModel>(source);

                return destination;

            }

        }

     

    The code below shows the code in the controller that actually performs the mapping

            public ActionResult Index()

            {

                var person = _personTasks.GetPerson(23);

     

                var mapper = new PersonToPersonViewModelMapper();

                var personViewModel = mapper.Map(person);

     

                return View(personViewModel);

            }

     

    As you can see from the code above even for a simple example it can get complicated quite quickly. Luckily AutoMapper offers an alternative approach – Profiles.

    Profiles allow you to group mapping configuration together, for example you could group mapping configuration by area or controller. The benefit of using profiles is that it removes the need for individual mapper classes, therefore reducing the complexity of your solution. In addition to this the act of creating the mapper configuration is quite a costly operation and if this logic in encapsulated in individual mapper classes this configuration is performed (unnecessarily) every time the mapper class is created but with profiles you initialize them once at application start up therefore improving the performance of your application.

    For the purposes of this example I created two profiles one responsible for containing the mapping configuration when mapping from domain objects to view models and the other for mapping from view models to domain objects. The two profile classes are shown below

        public class DomainToViewModelMappingProfile : Profile

        {

            public override string ProfileName

            {

                get { return "DomainToViewModelMappings"; }

            }

     

            protected override void Configure()

            {

                Mapper.CreateMap<Person, PersonViewModel>();

     

                Mapper.CreateMap<Address, AddressViewModel>()

                    .ForMember(x => x.PersonAddressLineOne, opt => opt.MapFrom(source => source.FirstLine))

                    .ForMember(x => x.PersonCountryOfResidence, opt => opt.MapFrom(source => source.Country));

     

                Mapper.CreateMap<Note, NoteViewModel>();

            }

        }

     

    And

         public class ViewModelToDomainMappingProfile : Profile

        {

            public override string ProfileName

            {

                get { return "ViewModelToDomainMappings"; }

            }

     

            protected override void Configure()

            {

                Mapper.CreateMap<PersonViewModel, Person>();

     

                Mapper.CreateMap<AddressViewModel, Address>()

                    .ForMember(x => x.FirstLine, opt => opt.MapFrom(source => source.PersonAddressLineOne))

                    .ForMember(x => x.Country, opt => opt.MapFrom(source => source.PersonCountryOfResidence));

     

                Mapper.CreateMap<NoteViewModel, Note>();

            }

        }

     

    To register the profiles you need to initialize AutoMapper at application start up so that it knows about the profiles. To do this I’ve created a helper class (shown below) which is responsible for initializing AutoMapper

        public class AutoMapperConfiguration

        {

            public static void Configure()

            {

                Mapper.Initialize(x =>

                {

                    x.AddProfile<DomainToViewModelMappingProfile>();

                    x.AddProfile<ViewModelToDomainMappingProfile>();

                });

            }

        }

     

    Then I call the Configure method from the Application_Start method of the Global.asax

            protected void Application_Start()

            {

                // Initialize automapper

                AutoMapperConfiguration.Configure();

     

                AreaRegistration.RegisterAllAreas();

     

                RegisterRoutes(RouteTable.Routes);

     

                // Setup spark view engine

                var settings = new SparkSettings();

     

                settings

                    .AddNamespace("System")

                    .AddNamespace("System.Collections.Generic")

                    .AddNamespace("System.Linq")

                    .AddNamespace("System.Web.Mvc")

                    .AddNamespace("System.Web.Mvc.Html");

     

                settings.AutomaticEncoding = true;

     

                ViewEngines.Engines.Add(new SparkViewFactory(settings));

            }

     

    To perform a mapping you simply to call the AutoMapper API and ask it to perform a mapping, example below

            public ActionResult Index()

            {

                var person = _personTasks.GetPerson(23);

     

                var personViewModel = AutoMapper.Mapper.Map<Person, PersonViewModel>(person);

     

                return View(personViewModel);

            }

     

    Obviously to improve testability you could encapsulate AutoMapper within a custom class which you supply to the controller via dependency injection.

    Attach to this post is the example solution.
  • Content Based Routing With WCF

    I’ve been looking at the new features included in WCF 4, one of the most interesting and powerful additions is the functionality provided by the RoutingService class (System.ServiceModel.Routing.RoutingService) in this post I’ll show an example of how to perform content based routing using the RoutingService class.

    The example scenario is as follows: orders are submitted to one of two services (both of which have the same contract), one service is responsible for processing low value orders (less than or equal to £5000) whilst the other service processes high value orders (over £5000). The reason two different services are required is that low value orders can be automatically processed whilst high value orders require human interaction to validate the order before the order can be processed. Ideally we do not want the client to know that there are two separate services and further to this we do not want them to be responsible for picking which service to send the order to, fortunately WCF 4 has functionality which enables a service to be exposed which will forward the request to another service based on the content of the request.

    Shown below is Order Service contract

        [ServiceContract]

        public interface IOrderService

        {

            [OperationContract]

            void ProcessOrder(Order order);

        }

    There are two implementations of this contract HumanWorkflowOrderService and StraightThroughProcessingOrderService, all these two services do is simply write out the details the received order to the Output window.

    The service the clients call into, which performs the content based routing needs to host the RoutingService, in fact no code is required at all to implement content based routing shown below is the contents of the service host file (in this example RoutingService.svc)

    <%@ ServiceHost Language="C#" Debug="true" Service="System.ServiceModel.Routing.RoutingService, System.ServiceModel.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>

     Next the content based routing needs to be configured so that when called the routing service knows where to forward the request to. Shown below is the service model configuration section.

      <system.serviceModel>

       

        <client>

          <endpoint address="http://localhost:1170/HumanWorkflowOrderService.svc"

                    binding="basicHttpBinding" contract="*" name="BasicHttpBinding_HumanWorkflowOrderService" />

          <endpoint address="http://localhost:1170/StraightThroughProcessingOrderService.svc"

                    binding="basicHttpBinding" contract="*" name="BasicHttpBinding_StraightThroughProcessingOrderService" />

        </client>

     

        <services>

          <service behaviorConfiguration="RoutingServiceBehavior"

            name="System.ServiceModel.Routing.RoutingService">

            <endpoint address="" binding="basicHttpBinding" name="RoutingServiceEndpoint" contract="System.ServiceModel.Routing.IRequestReplyRouter" />

          </service>

        </services>

     

        <behaviors>

          <serviceBehaviors>

            <behavior name="RoutingServiceBehavior">

              <serviceMetadata httpGetEnabled="true"/>

              <serviceDebug includeExceptionDetailInFaults="false" />

              <routing routingTableName="routingRules" filterOnHeadersOnly="false" />

            </behavior>

          </serviceBehaviors>

        </behaviors>

     

        <routing>

          <filters>

            <filter name="lessThan5kFilter" filterType="XPath" filterData="boolean(//*[local-name()= 'Price']/text() &lt;= 5000)"/>

            <filter name="greaterThan5kFilter" filterType="XPath" filterData="boolean(//*[local-name()= 'Price']/text() &gt; 5000)"/>

          </filters>

          <routingTables>

            <table name="routingRules">

              <entries>

                <add filterName="lessThan5kFilter" endpointName="BasicHttpBinding_StraightThroughProcessingOrderService"/>

                <add filterName="greaterThan5kFilter" endpointName="BasicHttpBinding_HumanWorkflowOrderService"/>

              </entries>

            </table>

          </routingTables>

        </routing>

       

      </system.serviceModel>

    The import things to notice are that the RoutingService implements the System.ServiceModel.Routing.IRequestReplyRouter contract which provides request reply functionality; there are other contracts that you could use if you wanted your service to behave differently e.g. ISimpleSessionRouter, IDuplexSessionRouter etc.

    The RoutingServiceBehavior includes the routing element which specifies what routing configuration to use (in our example “routingRules”) and also that content based routing can be performed on both the message header and message body.

    Next if you look at the routing sections this specifies two filters which use XPath to perform the routing evaluation (there are a number of different filters available all of which derive from System.ServiceModel.Dispatcher.MessageFilter). These filters are then used in the table section which specifies that when the filter’s criteria are matched which endpoint should be called. So in the example when the “lessThan5kFilter”filter evaluates successfully the “BasicHttpBinding_StraightThroughProcessingOrderService” endpoint is called.

    So as you can see using the new RoutingService it is very simple to configure your service to forward a message on to another service based on the content of the received message.

    I’ve attached the solution to this post; the solution also contains a readme file which explains how to run the application.

    Note: - That this post was written using Beta 1 of the .NET Framework 4.0 so therefore changes in future releases of the .NET Framework might break the example application

  • Workflow 4.0 Correlation with Message Headers

    I have continued to look at Workflow Foundation 4.0 which is included in the Beta 1 release of Visual Studio 2010 and .NET Framework 4.0, and I’ve been experimenting with the correlation functionality. The approach I have seen documented/blogged about most often is correlation at a workflow instance level, for example the same workflow instance will handle the processing of a related set of messages, whilst there is nothing wrong with this approach it does require you to manage the creation, persistence, loading and unloading of workflow instances instead of simply letting IIS manage the workflow instance lifecycle.

    Another approach is to do the correlation at the message level using the functionality provided by WCF which allows you to add custom data into message headers, and therefore you can use this data to perform correlation. This approach allows you to perform correlation across different workflows and workflow instances but however does require you to persist the message data (think BizTalk MessageBox database) so that different workflow instances can check the state of the processing to determine if further action is required. This approach also enablescorrelation to be performed using data that is not specified in the service contract and the data added to the message header could be anything. Below I will walk through an example which demonstrates this technique.

    The example scenario is as follows; an order is submitted but before the order can be taken to completion; the credit of the customer who placed the order needs to be checked that the requested products are in stock, in this imaginary example both the credit check and product stock check are submitted to one way services which will provide a response at some point in the future.

    The diagram below is the Order Service workflow, which is responsible for submitting the order to both customer (performs credit check) and product (performs stock check) services

    As you can see this workflow receives an order to process, it then calls the PersistOrderActivity which persists the order details, so that later in the process these details can be retrieved and used to confirm that the processing of the order is complete. Next the SubmitCreditCheckActivity is called which is responsible for submitting the credit check, then a ParallelForEach activity is used to call the SubmitStockCheckActivity (which submits the stock check) for each product contained in the order, as shown in the diagram below

    Finally the Order Service workflow returns to the caller, indicating that the request has been submitted.

    Shown below is the SubmitCreditCheckActivity

        public class SubmitCreditCheckActivity : CodeActivity

        {

            public InArgument<Order> Order { get; set; }

     

            protected override void Execute(CodeActivityContext context)

            {

                Order order = this.Order.Get(context);

     

                int orderId = order.Id;

                int customerId = order.Customer.Id;

                int orderPrice = order.Products.Sum(product => product.Price);

     

                // Set the address of the service the response from the customer service

                // should be sent back to

                string responseService = "http://localhost:1031/OrderValidationResponseService.xamlx";

     

                // Create a custom object to store in the message header

                CreditCheckResponseContext responseContext = new CreditCheckResponseContext { OrderId = orderId, ResponseAddress = responseService };

     

                MessageHeader<CreditCheckResponseContext> responseHeader = new MessageHeader<CreditCheckResponseContext>(responseContext);

     

                ChannelFactory<CustomerService.ICustomerService> factory = new ChannelFactory<CustomerService.ICustomerService>("BasicHttpBinding_ICustomerService");

                CustomerService.ICustomerService proxy = factory.CreateChannel();

     

                using (OperationContextScope contextScope = new OperationContextScope(proxy as IContextChannel))

                {

                    // Add custom data to the message header before calling the service

                    OperationContext.Current.OutgoingMessageHeaders.Add(responseHeader.GetUntypedHeader("ResponseHeader", "ServiceModelEx"));

     

                    proxy.VerifyAvailableCredit(customerId, orderPrice);

                }

            }

        }

    This activity is the first point in which any correlation based activity takes place, also it is worth noting that the Customer Service VerifyAvailableCredit operation is a one way call so therefore once called it will perform its work and not return a result further to this the operation may take a long time to complete, to cope with this the VerifiyAvailableCredit operation calls another service with the result of the operation when its work has completed. So that the service called on completion is not hard coded into the Customer Service the service to send the response to is supplied in custom message header data. The message header has been further customized to include the order id, this is so that the Customer Service can access the message header and pass the order id to the service called on completion, therefore enabling this service to correlate what order this credit check is for.

    Instead of adding custom data to the message header another choice would have been to change the service contract to include both the response service address and order id but this would have been wrong as these pieces of data are not required by the service to perform its work and by doing this it would have made it harder to figure out the intent of the service.

    The SubmitStockCheckActivity is very similar as it also sets the response service address and adds custom data to the message header.

    After the Order Service has completed the workflow instance is terminated and the Customer and Product Services continue to perform the various checks.  

    Shown below is the Customer Service contract and implementation.

        [ServiceContract]

        public interface ICustomerService

        {

            /// <summary>

            /// Checks if the customer has sufficient credit available

            /// </summary>

            /// <param name="customerId">The custom</param>

            /// <param name="orderPrice">The order price</param>

            [OperationContract(IsOneWay = true)]

            void VerifyAvailableCredit(int customerId, int orderPrice);

        }

        public class CustomerService : ICustomerService

        {

            /// <summary>

            /// Checks if the customer has sufficient credit available

            /// </summary>

            /// <param name="customerId">The custom</param>

            /// <param name="orderPrice">The order price</param>

            public void VerifyAvailableCredit(int customerId, int orderPrice)

            {

                // Get the amount of time to sleep the thread for (between 1 and 120 seconds)

                Random randomiser = new Random();

                int sleepInterval = randomiser.Next(1000, 120000);

     

                Thread.Sleep(sleepInterval);

     

                bool hasAvailableCredit = false;

     

                // If the customer id is less than 25 and the order price

                // is less than 500 - they have available credit

                if (customerId < 25 && orderPrice < 500)

                {

                    hasAvailableCredit = true;

                }

     

                // If the customer id is greater than 100 and the order price

                // is less than 5000 - they have available credit

                if (customerId > 100 && orderPrice < 5000)

                {

                    hasAvailableCredit = true;

                }

     

                // Call the response service passing in the message headers to

                // enable it to perform correlation

                CreditCheckResponseContext responseContext = OperationContext.Current.IncomingMessageHeaders.GetHeader<CreditCheckResponseContext>("ResponseHeader", "ServiceModelEx");

     

                EndpointAddress responseAddress = new EndpointAddress(responseContext.ResponseAddress);

     

                MessageHeader<CreditCheckResponseContext> responseHeader = new MessageHeader<CreditCheckResponseContext>(responseContext);

     

                ChannelFactory<OrderValidationResponseService.OrderValidationResponseServiceContract> factory = new ChannelFactory<OrderValidationResponseService.OrderValidationResponseServiceContract>("OrderValidationResponseService");

                OrderValidationResponseService.OrderValidationResponseServiceContract proxy = factory.CreateChannel(responseAddress);

     

                using (OperationContextScope contextScope = new OperationContextScope(proxy as IContextChannel))

                {

                    // Add custom message header before calling the response service

                    OperationContext.Current.OutgoingMessageHeaders.Add(responseHeader.GetUntypedHeader("ResponseHeader", "ServiceModelEx"));

     

                    proxy.OnCreditCheckResponse(new OnCreditCheckResponse(hasAvailableCredit));

                }

            }

        }

    As you can see the VerifyAvailableCredit method sleeps for a random number of seconds before evaluating if the customer has enough available credit, after that the method gets more interesting.

    Firstly it retrieves the custom data from the incoming message header, retrieves the address of the service which to send the response to, adds the custom data to the outgoing message header (to enable the service which handles the response to correlate the result with the correct order) and finally it calls the OnCreditCheckResponse method on the service which is expecting the result. The Product Service’s implementation is very similar to the implementation described above.

    Finally shown below is the OrderValidationResponse Service workflow which handles the results of both the credit check and stock check (sent from the Customer and Product services respectively), and works out if all responses for the order in question have been received and if they have continues processing the order.

    Below is the expanded pick activity, which exposes two service operations, OnStockCheckResponse and OnCreditCheckResponse

    When the OnStockCheckResponse service operation is invoked, the workflow calls the PersistStockCheckResponseActivity, which is responsible for retrieve the custom data from the message header and persisting the stock check result against the correct order and product (specified in the message header for correlation purposes).One the service operation has been handled the VerifyAllResponsesReceivedActivity checks that for the order specified in the custom message header that all responses have been received (customer credit check and all the product stock check responses), if all responses have been received the If activity shown below calls the ProcessOrderActivity which continues with order processing now that all the checks have been performed.

    I’ve attached the solution to this post; the solution also contains a readme file which explains how to run the application.

    Note: - That this post was written using Beta 1 of the .NET Framework 4.0 so therefore changes in future releases of the .NET Framework might break the example application

     

  • Workflow 4.0 Persistence/ Long Running Workflows

    I have recently started to look at the changes introduced with Visual Studio 2010 and .NET Framework 4 Beta 1, the first thing I have looked at is Workflow Foundation 4.0. In this post I will create a simple example which illustrates a long running workflow which persists its state to SQL Server.

    The example scenario is as follows; a request requiring approval is submitted to a workflow (via a WCF Service) and the workflow waits until at some point in the future the approval for the request is received and based on whether  the request is approved or not the workflow performs  a difference action. After the initial request has been submitted the workflow instance is persisted and unloaded and it is only reloaded when the approval for the request is submitted.

    Below is the WCF service contract exposed by the RequestService, this service is called by clients who submit both requests and request approvals.

        [ServiceContract]

        public interface IRequestService

        {

            [OperationContract]

            void AddRequest(Request request);

     

            [OperationContract]

            void SubmitApproval(RequestApproval requestApproval);

        }

    As you can see the service contract is very simple and consists of only two operations, shown below is the service implementation.

        public class RequestService : IRequestService

        {

            private static readonly ProcessRequestWorkflowHost processRequestHost = new ProcessRequestWorkflowHost();

     

            public void AddRequest(Request request)

            {

                processRequestHost.ProcessRequest(request);

            }

     

            public void SubmitApproval(RequestApproval requestApproval)

            {

                processRequestHost.SubmitRequestApproval(requestApproval);

            }

        }

    As you can see both operations forward the request to the ProcessRequestWorkflowHost class, this class is responsible for managing the creation, loading and persistence of the workflow instances. For this example I decided to manage the workflow instances manually in order to give me more control over the persistence of the workflow instances and the resumption of the workflow instances when approvals are submitted.

    The diagram below shows the workflow that is executed to process a request submission.

     

    When the workflow is executed the WriteLine activity is called which simply writes out the passed in request’s details (the request is passed in as an argument to the workflow) to the console application which is hosting the RequestService, then the WaitForRequestApproval activity is executed. This activity is implemented in C# as shown below.

        public class WaitForRequestApproval : NativeActivity<RequestApproval>

        {

            public InArgument<int> RequestId { get; set; }

     

            protected override void Execute(ActivityExecutionContext context)

            {

                // Create the bookmark which waits for the request approval

                string name = "Approval_" + this.RequestId.Get(context).ToString();

     

                context.CreateNamedBookmark(name, new BookmarkCallback(Callback));

            }

     

            /// <summary>

            /// Callback executed when the bookmark is resumed

            /// </summary>

            /// <param name="context"></param>

            /// <param name="bookmark"></param>

            /// <param name="state"></param>

            private void Callback(ActivityExecutionContext context, Bookmark bookmark, object state)

            {

                RequestApproval approval = (RequestApproval)state;

                context.SetValue(this.Result, approval);

            }

        }

    The WaitForRequestApproval activity defines a bookmark named “Approval_RequestId”, a bookmark defines a point at which the workflow waits for further information before execution can be continued when the bookmark is resumed the Callback method will be executed and the workflow will continue as normal.

    In our example once the bookmark has been resumed an If activity is executed (as illustrated in workflow diagram shown above), the expanded If activity is shown below.

     

    The If activity executes one of two WriteLine activities based on evaluating the condition (RequestApproval.IsApproved), these WriteLine activities simple write out the request Id and the approval status to the console.

    Finally shown below is the ProcessRequestWorkflowHost class, this class controls the creation of the workflow instances, the persistence of the workflow instances, the loading of workflow instances and bookmark resumption.

        public class ProcessRequestWorkflowHost

        {

            private IDictionary<int, Guid> requestToInstanceMapping;

     

            public ProcessRequestWorkflowHost()

            {

                // Setup mappings between request and workflow instance id - do this to save managing

                // the mappings else where

                this.requestToInstanceMapping = new Dictionary<int, Guid>();

                this.requestToInstanceMapping.Add(4, new Guid("56A2CA8F-3C64-485E-A0BC-A4F0E880898C"));

                this.requestToInstanceMapping.Add(5, new Guid("F130B19A-1B4B-43DA-B75B-6C58F0CC6419"));

                this.requestToInstanceMapping.Add(13, new Guid("3B70FAFF-5FDC-4159-836F-DFD4DFF2EE4E"));

                this.requestToInstanceMapping.Add(26, new Guid("BFB619F7-2BD7-4D52-99FA-97C20FA95DCE"));

                this.requestToInstanceMapping.Add(55, new Guid("2D15D97F-ABCB-45C5-AC7D-F18A64F1E2E3"));

            }

     

            /// <summary>

            /// Loads a workflow instance with the specified

            /// instance id

            /// </summary>

            /// <param name="instanceId">Workflow instance id</param>

            /// <returns>Workflow instance</returns>

            public WorkflowInstance LoadInstance(Guid instanceId)

            {

                // Setup the persistance

                PersistenceProvider persistenceProvider = this.CreatePersistanceProvider(instanceId);

     

                // Load the ProcessRequest workflow

                WorkflowElement wf = WorkflowXamlServices.Load(File.OpenRead("ProcessRequest.xaml")) as WorkflowElement;

     

                // Retrieve the workflow instance

                WorkflowInstance instance = WorkflowInstance.Load(wf, persistenceProvider);

     

                return instance;

            }

     

            /// <summary>

            /// Processes the specified Request

            /// </summary>

            /// <param name="request">Request to process</param>

            public void ProcessRequest(Request request)

            {

                // Get the workflow instance id to use

                Guid instanceId = this.requestToInstanceMapping[request.Id];

     

                // Setup the arguments that are passed to the workflow

                IDictionary<string, object> input = new Dictionary<string, object>();

                input.Add("Request", request);

     

                // Load the ProcessRequest workflow

                WorkflowElement wf = WorkflowXamlServices.Load(File.OpenRead("ProcessRequest.xaml")) as WorkflowElement;

     

                // Create the workflow instance specifying the arguments and instance id

                WorkflowInstance instance = new WorkflowInstance(wf, input, instanceId);

                // When instance is idle unload and persist the isntance

                instance.OnIdle = () => IdleAction.Unload;

         

                // Setup the persistance

                PersistenceProvider persistenceProvider = this.CreatePersistanceProvider(instanceId);

                instance.Extensions.Add(persistenceProvider);

     

                // Start the workflow instance

                instance.Run();

            }

     

            /// <summary>

            /// Submits the request approval

            /// </summary>

            /// <param name="approval">Request approval</param>

            public void SubmitRequestApproval(RequestApproval approval)

            {

                // Get the workflow instance id to use

                Guid instanceId = this.requestToInstanceMapping[approval.RequestId];

     

                // Load the workflow instance

                WorkflowInstance instance = this.LoadInstance(instanceId);

     

                // Resume the workflow at the bookmark

                string bookmark = "Approval_" + approval.RequestId.ToString();

                instance.ResumeBookmark(bookmark, approval);

            }

     

            /// <summary>

            /// Creates the persistence provider

            /// </summary>

            /// <param name="instanceId">Workflow instance the persistence provider is for</param>

            /// <returns>Persistance provider</returns>

            private PersistenceProvider CreatePersistanceProvider(Guid instanceId)

            {

                string persistenceConnectionString = "Data Source=localhost;Initial Catalog=SampleInstanceStore;Integrated Security=True;Asynchronous Processing=True";

     

                // Create and open the provider factory

                SqlPersistenceProviderFactory factory = new SqlPersistenceProviderFactory(persistenceConnectionString, true, false, new TimeSpan(0, 1, 0));

                factory.Open();

     

                // Create the persistance provider

                PersistenceProvider persistenceProvider = factory.CreateProvider(instanceId);

     

                return persistenceProvider;

            }

        }

    The constructor creates a list of mappings between request ids and workflow instance ids; I have done this to save adding further code to manage the relationship between the requests and the workflow instances – so therefore at the moment this example will only work with a specified set of request ids (4, 5, 13, 26 and 55).

    The ProcessRequest method is called by the RequestService when a new request is submitted, the method creates the arguments to pass to the ProcessRequest workflow, creates a new workflow instance adds the persistence provider to the instance (enabling the instance to be persisted) and finally executes the workflow. Note that the workflow instance is only persisted when the instance becomes idle, when the OnIdle event is raised by the instance the IdleAction is set to Unload – which specifies that the workflow instance is persisted and then unloaded.

    At some point in the future the approval for the request will be submitted, the SubmitRequestApproval method is called by the RequestService passing in the request approval, firstly this method calls the LoadInstance method which retrieves the specified workflow instance from the persistence store, then the previously created bookmark is resumed therefore enabling the workflow to continue to completion.

    When developing this sample application I had a few problems getting the persistence to work it turns out this is because for certain persistence scenarios you need to use the Workflow 3.5 SQL Schema and whilst for others the Workflow 4.0 SQL Schema. In short for WorkflowServiceHost usage you need to use the 4.0 schemas but for WorkflowInstance usage the 3.5 schema. Have a look at http://kennyw.com/work/workflow/350 for more information; it seems that this feature will be fixed in beta 2.

    I’ve attached the solution to this post; the solution also contains a readme file which explains how to setup the persistence and how to run the application.

    Note: - That this post was written using Beta 1 of the .NET Framework 4.0 so therefore changes in future releases of the .NET Framework might break the example application

  • Querying Collections Using the Specification Pattern and Expression Trees

    When Linq was initially introduced, I thought it was one of the most useful additions that have ever been made to .NET. I still think that now but after working with Linq for a while I’ve come to the conclusion that it can introduce several problems:

    • Queries are scattered all over the code base
    • There is no common reusable query mechanism
    • Numerous identical or similar queries are repeated (violating DRY – don’t repeat yourself)
    • A change to an entity (e.g. renaming a property) can affect many classes which contain queries that use that property
    • It is very easy to introduce bugs in Linq queries as it is impossible to just unit test the code which is querying a collection in isolation

    This led me to initially conclude that the Specification pattern might be the answer as this enables the ability to define encapsulated, reusable and testable queries. Shown below is the OrderProcess class which initially makes use of simple Linq queries, which I shall use to demonstrate how to refactor to use the Specification pattern.

        public class OrderProcess

        {

            public List<Order> GetCompletedOrders(List<Order> orders)

            {

                List<Order> completedOrders = orders.Where(order => order.IsCompleted

                                                                    && order.Products.Count > 0).ToList();

     

                return completedOrders;

            }

     

            public List<Order> GetCustomerOrders(List<Order> orders, Customer customer)

            {

                List<Order> customerOrders = orders.Where(order => order.Customer.Id.Equals(customer.Id)).ToList();

     

                return customerOrders;

            }

     

            public List<Order> GetCustomerCompletedOrders(List<Order> orders, Customer customer)

            {

                List<Order> customerCompletedOrders = orders.Where(order => order.Customer.Id.Equals(customer.Id)

                                                                            && order.IsCompleted

                                                                            && order.Products.Count > 0).ToList();

     

                return customerCompletedOrders;

            }

        }

    Shown below is the Specification base class, which all specifications derive from.

        public abstract class Specification<Entity>

        {

            public abstract bool IsSatisfiedBy(Entity candidate);

     

            public Specification<Entity> And(Specification<Entity> specification)

            {

                return new AndSpecification<Entity>(this, specification);

            }

     

            public Specification<Entity> Or(Specification<Entity> specification)

            {

                return new OrSpecification<Entity>(this, specification);

            }

     

            public Specification<Entity> Not(Specification<Entity> specification)

            {

                return new NotSpecification<Entity>(this);

            }

        }

    To enable the ability to chain specifications using And/Or logic I have implemented specifications which enable this functionality, below is the AndSpecification class.

        public class AndSpecification<Entity> : Specification<Entity>

        {

            private readonly Specification<Entity> leftSide;

            private readonly Specification<Entity> rightSide;

     

            public AndSpecification(Specification<Entity> leftSide, Specification<Entity> rightSide)

            {

                this.leftSide = leftSide;

                this.rightSide = rightSide;

            }

     

            public override bool IsSatisfiedBy(Entity candidate)

            {

                return leftSide.IsSatisfiedBy(candidate) && rightSide.IsSatisfiedBy(candidate);

            }

        }

    Next I needed to implement the specifications that encapsulate the different queries that can be performed against the Order entity. Shown below is the OrderProductCountGreaterThanSpecification class which is responsible for ensuring that Orders have more than the specified number of products.

        public class OrderProductCountGreaterThanSpecification : Specification<Order>

        {

            private readonly int productCount;

     

            public OrderProductCountGreaterThanSpecification(int productCount)

            {

                this.productCount = productCount;

            }

     

            public override bool IsSatisfiedBy(Order candidate)

            {

                return candidate.Products.Count > productCount;

            }

        }

    Below is the OrderProcess class which has been refactored to make use of the new specification classes.

        public class OrderProcess

        {

            public List<Order> GetCompletedOrders(List<Order> orders)

            {

                List<Order> completedOrders = orders.Where(order => new OrderProductCountGreaterThanSpecification(0)

                                                                        .And(new OrderIsCompletedSpecification())

                                                                        .IsSatisfiedBy(order)).ToList();

     

                return completedOrders;

            }

     

            public List<Order> GetCustomerOrders(List<Order> orders, Customer customer)

            {

                List<Order> customerOrders = orders.Where(order => new OrderCustomerSpecification(customer)

                                                                       .IsSatisfiedBy(order)).ToList();

     

                return customerOrders;

            }

     

            public List<Order> GetCustomerCompletedOrders(List<Order> orders, Customer customer)

            {

                List<Order> customerCompletedOrders = orders.Where(order => new OrderProductCountGreaterThanSpecification(0)

                                                                                .And(new OrderIsCompletedSpecification())

                                                                                .And(new OrderCustomerSpecification(customer))

                                                                                .IsSatisfiedBy(order)).ToList();

     

                return customerCompletedOrders;

            }

        }

    Once I had done this I was still not 100% satisfied, as I found the code hard to read, bloated and the intent of the queries is not obvious without understanding exactly what each specification is doing. What I really wanted was something that had a fluent API and therefore is very easy to see what the intent of the query is, but still had the features offered by the Specification pattern (e.g. encapsulation/reusable and the ability to chain specifications using And/Or).

    So after much reading/surfing I came to the conclusion that expression trees offered the functionality I required, as they have the ability to create queries on the fly. So I created a specification which used expression trees to build up and execute the required query this class OrderSpecification is shown below.

        public class OrderSpecification : Specification<Order>

        {

            private Expression<Func<Order, bool>> expression;

     

            public OrderSpecification WithIsCompleted()

            {

                addExpression(order => order.IsCompleted);

                return this;

            }

     

            public OrderSpecification WithMoreProductsThan(int count)

            {

                addExpression(order => order.Products.Count > count);

                return this;

            }

     

            public OrderSpecification WithCustomer(Customer customer)

            {

                addExpression(order => order.Customer.Id.Equals(customer.Id));

                return this;

            }

     

            private void addExpression(Expression<Func<Order, bool>> expression)

            {

                if (this.expression == null)

                {

                    this.expression = expression;

                }

                else

                {

                    this.expression = ConcatenateExpressions(expression);

                }

            }

     

            private Expression<Func<Order, bool>> ConcatenateExpressions(Expression<Func<Order, bool>> rightSide)

            {

                // Create an invocation expression (expression that applies a lambda to a list of expressions argument)

                InvocationExpression rightSideInvoke = Expression.Invoke(rightSide, expression.Parameters.Cast<Expression>());

     

                // Create a binary operation between the two expressions

                BinaryExpression binaryExpression = Expression.MakeBinary(ExpressionType.AndAlso, expression.Body, rightSideInvoke);

     

                // Create the lambda

                return Expression.Lambda<Func<Order, bool>>(binaryExpression, expression.Parameters);

            }

     

            public override bool IsSatisfiedBy(Order candidate)

            {

                return expression.Compile().Invoke(candidate);

            }

        }

    The final version of the OrderProcess class which makes use of this new specification is shown below.

        public class OrderProcess

        {

            public List<Order> GetCompletedOrders(List<Order> orders)

            {

                List<Order> completedOrders = orders.Where(order => new OrderSpecification()

                                                            .WithIsCompleted()

                                                            .WithMoreProductsThan(0)

                                                            .IsSatisfiedBy(order)).ToList();

     

                return completedOrders;

            }

     

            public List<Order> GetCustomerOrders(List<Order> orders, Customer customer)

            {

                List<Order> customerOrders = orders.Where(order => new OrderSpecification()

                                                                        .WithCustomer(customer)

                                                                        .IsSatisfiedBy(order)).ToList();

     

                return customerOrders;

            }

     

            public List<Order> GetCustomerCompletedOrders(List<Order> orders, Customer customer)

            {

                List<Order> customerCompletedOrders = orders.Where(order => new OrderSpecification()

                                                                    .WithIsCompleted()

                                                                    .WithCustomer(customer)

                                                                    .WithMoreProductsThan(0)

                                                                    .IsSatisfiedBy(order)).ToList();

     

                return customerCompletedOrders;

            }

        }

    As you can see the OrderProcess class is now much more readable and the intention of the queries is now clear. Additionally as the OrderSpecification inherits from the Specification base class it can be used in conjunction with other specifications for example.

                orders.Where(order => new OrderSpecification()

                                          .WithCustomer(customer)

                                          .And(new OrderProductCountGreaterThanSpecification(10))

                                          .IsSatisfiedBy(order)).ToList();
  • Don’t Mix Object Creation with Business Logic

    I’ve come to the conclusion that mixing object creation logic (e.g. new statements) with business logic is a bad idea; this is because

    • A method should only be responsible for one thing (Single Responsibility Principle), either it creates things or performs logic on things not both.
    • Code littered with both creation logic and business logic tends to be long and hard to read.
    • It is good practice to pass dependencies into a class (dependency injection) in order to promote looser coupling.
    • If a method creates its dependencies it is very hard to unit test using a framework such as Rhino Mocks.

    The OrderProcess class shown below is a good example of why mixing object creation logic with business logic is a bad idea.

        /// <summary>

        /// Order process

        /// </summary>

        public class OrderProcess

        {

            /// <summary>

            /// Processes the payment of the order

            /// </summary>

            /// <param name="order">The order</param>

            /// <param name="paymentMethod">The method of payment</param>

            public void ProcessPayment(Order order, PaymentMethod paymentMethod)

            {

                // Calculate the order's total price

                order.TotalPrice = order.Products.Sum(product => product.Price);

     

                // If the customer is a premium customer apply a discount

                // to the price

                if (CustomerType.Premium.Equals(order.Customer))

                {

                    order.TotalPrice -= 50;

                }

     

                // Get the payment processor based on

                // the method of payment

                IPaymentProcessor paymentProcessor = null;

     

                switch (paymentMethod)

                {

                    case PaymentMethod.Cash:

                        paymentProcessor = new CashPaymentProcessor();

                        break;

                    case PaymentMethod.Cheque:

                        paymentProcessor = new ChequePaymentProcessor();

                        break;

                    case PaymentMethod.CreditCard:

                        paymentProcessor = new CreditCardPaymentProcessor();

                        break;

                }

     

                // Process the order payment

                if (paymentProcessor != null)

                {

                    paymentProcessor.Process(order);

                }

            }

        }

    As you can see the ProcessPayment method is responsible for both business logic (working out the order price and applying a discount) and creating a payment processor based on the method of payment. The code would be much cleaner if the decision on which payment processor to use was another class’s responsibility. To accomplish this I’ve extracted the logic that is responsible for creating the payment processor into a factory and passed an instance of this factory into the OrderProcess class as shown below.

        /// <summary>

        /// Payment processor factory

        /// </summary>

        public class PaymentProcessorFactory : IPaymentProcessorFactory

        {

            /// <summary>

            /// Creates a payment processor based on the

            /// method of payment

            /// </summary>

            /// <param name="paymentMethod">Method of payment</param>

            /// <returns>Payment processor instance</returns>

            public IPaymentProcessor CreatePaymentProcessor(PaymentMethod paymentMethod)

            {

                // Get the payment processor based on

                // the method of payment

                IPaymentProcessor paymentProcessor = new NullPaymentProcessor();

     

                switch (paymentMethod)

                {

                    case PaymentMethod.Cash:

                        paymentProcessor = new CashPaymentProcessor();

                        break;

                    case PaymentMethod.Cheque:

                        paymentProcessor = new ChequePaymentProcessor();

                        break;

                    case PaymentMethod.CreditCard:

                        paymentProcessor = new CreditCardPaymentProcessor();

                        break;

                }

     

                return paymentProcessor;

            }

        }

        /// <summary>

        /// Order process

        /// </summary>

        public class OrderProcess

        {

            /// <summary>

            /// Payment processor factory instance

            /// </summary>

            private readonly IPaymentProcessorFactory paymentProcessorFactory;

     

            /// <summary>

            /// Initializes a new instance of the OrderProcess class

            /// </summary>

            /// <param name="paymentProcessorFactory">Payment processor factory</param>

            public OrderProcess(IPaymentProcessorFactory paymentProcessorFactory)

            {

                this.paymentProcessorFactory = paymentProcessorFactory;

            }

     

            /// <summary>

            /// Processes the payment of the order

            /// </summary>

            /// <param name="order">The order</param>

            /// <param name="paymentMethod">The method of payment</param>

            public void ProcessPayment(Order order, PaymentMethod paymentMethod)

            {

                // Calculate the order's total price

                order.TotalPrice = order.Products.Sum(product => product.Price);

     

                // If the customer is a premium customer apply a discount

                // to the price

                if (CustomerType.Premium.Equals(order.Customer))

                {

                    order.TotalPrice -= 50;

                }

     

                // Process the order payment

                IPaymentProcessor paymentProcessor = this.paymentProcessorFactory.CreatePaymentProcessor(paymentMethod);

                paymentProcessor.Process(order);

            }

        }

    As you can see it is now much clearer what the ProcessPayment method is doing now that the object creation logic has been removed. In addition to this the OrderProcess class is now much easier to unit test as the IPaymentProcessorFactory instance passed to the constructor can be mocked or stubbed very easily. There other benefits including if we added a new method of payment (and therefore a new payment processor) no change would need to be made to the OrderProcess class as the change would be isolated to the PaymentProcessorFactory.

  • Using the Object Builder Pattern to Manage Test Data

    During my last project it became apparent that we had no consistency in how we created the data used in our unit tests; listed below are some of the various different solutions that had been implemented

    • Private helper methods that created entities, often these methods had been cut and paste into other unit test classes
    • Creating and setting properties on the entities in the test method
    • Several helper classes that were used by some of the unit tests

    All of the above highlighted firstly that we were not treating our unit test classes as first class citizens (e.g. the tests did not always following the coding standards used, were poorly commented and there was no code reuse between any of the tests). To fix this going forwards we started to treat unit tests as first class citizens and implementing them as we would implement a feature in the main code base.

    To address the problem of how to manage the data used in the unit tests we decided to use the object builder pattern; the object builder pattern enabled us to have:

    •  A single and consistent method of creating entities
    • Easy to extend to enable different property values to be set
    • Fluent API
    • Ability to chain object builders to compose objects as required

    Below is the OrderProcess class that I am going to use to demonstrate how to write unit tests that utilize the object builder pattern for creating test data.

        /// <summary>

        /// Order process class

        /// </summary>

        public class OrderProcess

        {

            /// <summary>

            /// Checks to verify that the customer has a enough

            /// credit to place the order

            /// </summary>

            /// <param name="order">Order to verify</param>

            /// <exception cref="ValidationException">Exception thrown if customer has insufficient credit</exception>

            public void VerifyCustomerCredit(Order order)

            {

                // Get the total cost of the order

                int orderCost = order.Products.Sum(product => product.Price);

     

                // Checks the customer has sufficient credit

                if (orderCost > order.Customer.Credit)

                {

                    throw new ValidationException("Order cannot be processed, customer does not have enough credit");

                }

            }

     

            /// <summary>

            /// Checks to verify that order does not contain more than the

            /// maximum number of items that the customer is allowed to order

            /// </summary>

            /// <param name="order">Order to verify</param>

            /// <exception cref="ValidationException">Exception thrown if customer has created an order with too many items</exception>

            public void VerifyNumberOfItems(Order order)

            {

                if (order.Products.Count > order.Customer.MaximumItemsPerOrder)

                {

                    throw new ValidationException("Order cannot be processed, too many items in order");

                }

            }

     

            /// <summary>

            /// Applies a discount to the order

            /// </summary>

            /// <param name="order">Order to apply the discount to</param>

            public void ApplyDiscount(Order order)

            {

                // Only apply the discount if the customer is a premium customer

                if (CustomerStatus.Premium.Equals(order.Customer.Status))

                {

                    order.Discount = 50;

                }

            }

        }

    To help test the OrderProcess class I’ve implemented an object builder per entity (Order, Product and Customer). The object builders are shown below.

    /// <summary>

        /// Object builder for creating test customer objects

        /// </summary>

        public class CustomerBuilder

        {

            /// <summary>

            /// Customer credit limit

            /// </summary>

            private int credit = 5000;

     

            /// <summary>

            /// Customer Id

            /// </summary>

            private int id = 1;

     

            /// <summary>

            /// Maximum number of items the customer can place per order

            /// </summary>

            private int maximumItemsPerOrder = 100;

     

            /// <summary>

            /// Customer status

            /// </summary>

            private CustomerStatus status = CustomerStatus.Basic;

     

            /// <summary>

            /// Specifies the customer's credit limit

            /// </summary>

            /// <param name="credit">Credit limit</param>

            /// <returns>Builder instance</returns>

            public CustomerBuilder WithCredit(int credit)

            {

                this.credit = credit;

                return this;

            }

     

            /// <summary>

            /// Specifies the customer's maximum items per order

            /// </summary>

            /// <param name="maximumItemsPerOrder">Maximum number of items per order</param>

            /// <returns>Builder instance</returns>

            public CustomerBuilder WithMaximumItemsPerOrder(int maximumItemsPerOrder)

            {

                this.maximumItemsPerOrder = maximumItemsPerOrder;

                return this;

            }

     

            /// <summary>

            /// Specifies the customer's status

            /// </summary>

            /// <param name="status">Customer status</param>

            /// <returns>Builder instance</returns>

            public CustomerBuilder WithStatus(CustomerStatus status)

            {

                this.status = status;

                return this;

            }

     

            /// <summary>

            /// Builds a Customer entity

            /// </summary>

            /// <returns>Customer entity</returns>

            public Customer Build()

            {

                return new Customer

                           {

                                   Id = this.id,

                                   Credit = this.credit,

                                   MaximumItemsPerOrder = this.maximumItemsPerOrder,

                                   Status = this.status

                           };

            }

        }

    As you can see the CustomerBuilder class has a default value definied for each of the properties on the Customer entity and if you simply called the Build method it would return a Customer entity with every property set to a sensible default value. If you need to be able to set a particular property on the Customer object you simple add a WithXXX method for example to set the customer’s status you would call the WithStatus method specifying the required status. You will notice the WithXXX methods all return an instance of the object builder therefore allowing you to chain method calls for example to set both the customer’s credit and status you would call the builder as follows.

                Customer customer = new CustomerBuilder()

                                        .WithCredit(60)

                                        .WithStatus(CustomerStatus.Premium)

                                        .Build();

    Below are the ProductBuilder and OrderBuilder classes

        /// <summary>

        /// Object builder for creating test product objects

        /// </summary>

        public class ProductBuilder

        {

            /// <summary>

            /// Product's id

            /// </summary>

            private int id = 1;

     

            /// <summary>

            /// Product's name

            /// </summary>

            private string name = "My Product";

     

            /// <summary>

            /// Product's price

            /// </summary>

            private int price = 10;

     

            /// <summary>

            /// Specifies the product's price

            /// </summary>

            /// <param name="price">Product's price</param>

            /// <returns>Builder instance</returns>

            public ProductBuilder WithPrice(int price)

            {

                this.price = price;

                return this;

            }

     

            /// <summary>

            /// Builds a Product entity

            /// </summary>

            /// <returns>Product entity</returns>

            public Product Build()

            {

                return new Product

                           {

                                   Id = this.id,

                                   Name = this.name,

                                   Price = this.price

                           };

            }

        }

    /// <summary>

        /// Object builder for creating test order objects

        /// </summary>

        public class OrderBuilder

        {

            /// <summary>

            /// List of products that make up the order

            /// </summary>

            private readonly List<Product> products = new List<Product>();

     

            /// <summary>

            /// Customer who placed the order

            /// </summary>

            private Customer customer = new CustomerBuilder().Build();

     

            /// <summary>

            /// Order discount

            /// </summary>

            private int discount;

     

            /// <summary>

            /// Order id

            /// </summary>

            private int id = 1;

     

            /// <summary>

            /// Specifies the customer who placed the order

            /// </summary>

            /// <param name="customer">Customer who placed the order</param>

            /// <returns>Builder instance</returns>

            public OrderBuilder WithCustomer(Customer customer)

            {

                this.customer = customer;

                return this;

            }

     

            /// <summary>

            /// Specifies a product to add to the order

            /// </summary>

            /// <param name="product">Product to add to the order</param>

            /// <returns>Builder instance</returns>

            public OrderBuilder WithProduct(Product product)

            {

                this.products.Add(product);

                return this;

            }

     

            /// <summary>

            /// Builds an Order entity

            /// </summary>

            /// <returns>Order entity</returns>

            public Order Build()

            {

                return new Order

                           {

                                   Id = this.id,

                                   Customer = this.customer,

                                   Products = this.products,

                                   Discount = this.discount

                           };

            }

        }

    The OrderBuilder class is more complex than the previous builders and makes use of the other builders, for example the Order entity has a Customer property instead of creating a new instance of a Customer entity the OrderBuilder makes use of the CustomerBuilder to ensure that by default it has a fully and correctly constructed Customer entity. The Order entity also contains a list of products to help populate the list the OrderBuilder exposes a WithProduct method which adds the specified product to the list. Shown below is an example of how all three object builders could be chained together.

                Order order =

                        new OrderBuilder()

                        .WithProduct(new ProductBuilder().WithPrice(100).Build())

                        .WithProduct(new ProductBuilder().WithPrice(200).Build())

                        .WithCustomer(new CustomerBuilder().WithCredit(50).Build())

                        .Build();

    Finally shown below is the OrderProcessTest class which is responsible for testing the OrderProcess class, to achieve this it makes use of the object builders shown above.

    /// <summary>

        /// OrderProcess tests

        /// </summary>

        [TestClass]

        public class OrderProcessTests

        {

            /// <summary>

            /// Tests that a ValidationException is thrown when the customer does not have

            /// enough credit to pay for the order

            /// </summary>

            [TestMethod]

            [ExpectedException(typeof(ValidationException))]

            public void VerifyCustomerCredit_When_Customer_Credit_Less_Than_Order_Cost()

            {

                // Arrange

                Order order =

                        new OrderBuilder()

                        .WithProduct(new ProductBuilder().WithPrice(100).Build())

                        .WithProduct(new ProductBuilder().WithPrice(200).Build())

                        .WithCustomer(new CustomerBuilder().WithCredit(50).Build())

                        .Build();

     

                // Act

                OrderProcess process = new OrderProcess();

                process.VerifyCustomerCredit(order);

            }

     

            /// <summary>

            /// Tests that no ValidationException is thrown when the customer does have

            /// enough credit to pay for the order

            /// </summary>

            [TestMethod]

            public void VerifyCustomerCredit_When_Customer_Credit_Greater_Than_Order_Cost()

            {

                // Arrange

                Order order =

                        new OrderBuilder()

                        .WithProduct(new ProductBuilder().WithPrice(100).Build())

                        .WithProduct(new ProductBuilder().WithPrice(200).Build())

                        .WithCustomer(new CustomerBuilder().WithCredit(5000).Build())

                        .Build();

     

                // Act

                OrderProcess process = new OrderProcess();

                process.VerifyCustomerCredit(order);

            }

     

            /// <summary>

            /// Tests that a ValidationException is thrown when the customer has created an

            /// order with too many items

            /// </summary>

            [TestMethod]

            [ExpectedException(typeof(ValidationException))]

            public void VerifyNumberOfItems_When_Maximum_Items_Exceeded()

            {

                // Arrange

                Order order =

                        new OrderBuilder().WithProduct(new ProductBuilder().Build())

                        .WithProduct(new ProductBuilder().Build())

                        .WithProduct(new ProductBuilder().Build())

                        .WithCustomer(new CustomerBuilder().WithMaximumItemsPerOrder(2).Build())

                        .Build();

     

                // Act

                OrderProcess process = new OrderProcess();

                process.VerifyNumberOfItems(order);

            }

     

            /// <summary>

            /// Tests that the discount is applied for a premium customer

            /// </summary>

            [TestMethod]

            public void ApplyDiscount_When_Customer_Status_Premium()

            {

                // Arrange

                Order order =

                        new OrderBuilder()

                        .WithCustomer(new CustomerBuilder().WithStatus(CustomerStatus.Premium).Build())

                        .Build();

     

                // Act

                OrderProcess process = new OrderProcess();

                process.ApplyDiscount(order);

     

                // Assert

                Assert.AreEqual(50, order.Discount);

            }

     

            /// <summary>

            /// Test that the discount is not applied for non premium customers

            /// </summary>

            [TestMethod]

            public void ApplyDiscount_When_Customer_Status_Basic()

            {

                // Arrange

                Order order =

                        new OrderBuilder()

                        .WithCustomer(new CustomerBuilder().WithStatus(CustomerStatus.Basic).Build())

                        .Build();

     

                // Act

                OrderProcess process = new OrderProcess();

                process.ApplyDiscount(order);

     

                // Assert

                Assert.AreEqual(0, order.Discount);

            }

        }

  • Extending Functionality with the Strategy Pattern

    The strategy pattern enables the functionality of an application to be easily extended or modified to cope with new or changed requirements, as shown in the following example.

    The code below shows the OrderProcess class which is responsible for processing the payment of an order as shown in the ProcessOrderPayment method

        public class OrderProcess

        {

            private readonly IOrderRepository repository;

     

            public OrderProcess(IOrderRepository repository)

            {

                this.repository = repository;

            }

     

            public void ProcessOrderPayment(Order order, PaymentDetails paymentDetails)

            {

                //Work out the order's price

                CalculateOrderPrice(order);

     

                //Process the payment

                switch (paymentDetails.Method)

                {

                    case PaymentMethod.CreditCard:

                        ProcessCreditCardPayment(order.Price, paymentDetails);

                        order.PaymentTaken = true;

                        break;

                    case PaymentMethod.Cheque:

                        ProcessChequePayment(order.Price, paymentDetails);

                        order.PaymentTaken = true;

                        break;

                }

     

                //Persist changes to the order

                repository.Save(order);

            }

     

            private void CalculateOrderPrice(Order order)

            {

                //Code to calculate order price

                order.Price = 500;

            }

     

            private void ProcessCreditCardPayment(int amount, PaymentDetails paymentDetails)

            {

                //Code to process credit card payment

            }

     

            private void ProcessChequePayment(int amount, PaymentDetails paymentDetails)

            {

                //Code to process cheque payment

            }

        }

    The current implementation has the following issues

    • If a payment method is added the OrderProcess class will have to be changed, therefore violating the open closed principal
    • If the implementation of a payment method is changed, e.g. a new payment service provider used to process credit card payments the OrderProcess class is not isolated from this change.
    • The class is hard to unit test as it has numerous responsibilities and therefore it is difficult to setup tests to ensure all possible code paths are tested
    • The OrderProcess class will get very large and complex if more payment methods are added

    To solve the problems listed above we need to isolate the functionality that is most likely to change, in our example this is the processing of payments, this can be achieve by using the strategy pattern; below is the description from the GoF book.

    “Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently”

    Shown below is the PaymentStrategyBase class which is the base class for the various payment mechanisms.

        public abstract class PaymentStrategyBase

        {

            protected PaymentDetails PaymentDetails { get; private set; }

     

            protected PaymentStrategyBase(PaymentDetails paymentDetails)

            {

                PaymentDetails = paymentDetails;

            }

     

            public abstract void Process(int amount);

        }

    Next shown are the implementations of the strategies for handling credit card payments and cheque payments.

        public class CreditCardPaymentStrategy : PaymentStrategyBase

        {

            public CreditCardPaymentStrategy(PaymentDetails paymentDetails) : base(paymentDetails){}

     

            public override void Process(int amount)

            {

                //Process credit card payment

            }

        }

        public class ChequePaymentStrategy : PaymentStrategyBase

        {

            public ChequePaymentStrategy(PaymentDetails paymentDetails) : base(paymentDetails) { }

     

            public override void Process(int amount)

            {

                //Process cheque payment

            }

        }

    Below is the modified OrderProcess class which now uses the new classes

        public class OrderProcess

        {

            private readonly IOrderRepository repository;

     

            public OrderProcess(IOrderRepository repository)

            {

                this.repository = repository;

            }

     

            public void ProcessOrderPayment(Order order, PaymentStrategyBase payment)

            {

                //Work out the order's price

                CalculateOrderPrice(order);

     

                //Process the payment

                payment.Process(order.Price);

                order.PaymentTaken = true;

     

                //Persist changes to the order

                repository.Save(order);

            }

     

            private void CalculateOrderPrice(Order order)

            {

                //Code to calculate order price

                order.Price = 500;

            }

        }

    As you can see the OrderProcess class is now a lot simpler so therefore is much easier to maintain and write unit tests for, also the different strategies are simple to maintain and test. Now the ProcessOrderPayment method has no knowledge of how the payment is being processed so therefore a new payment strategy implementation could be added without modifying the OrderProcess class or the implementation of an existing strategy changed. For example if a new requirement was that the application needs to be able to process payments via PayPal we could implement the class shown below.

        public class PayPalPaymentStrategy : PaymentStrategyBase

        {

            public PayPalPaymentStrategy(PaymentDetails paymentDetails) : base(paymentDetails) { }

     

            public override void Process(int amount)

            {

                //Process paypal payment

            }

        }

    For the application to make use of the new PayPalPaymentStrategy class we would need to ensure that the code that uses the OrderProcess class instantiates the correct strategy to pass to the ProcessOrderPayment method, this creation logic could be encapsulated within a factory.
  • Unit Testing With Rhino Mocks

    I’ve been asked on a few occasions by my colleagues how I approach unit testing with Rhino Mocks; my approach has changed since Rhino Mocks 3.5 with the new Arrange Act Assert (AAA) syntax was released, so I thought I would write about why I use Rhino Mocks and show some example tests.

    The reasons I use Rhino Mocks are

    • It allows me to do interaction testing (how classes interact with each other)
    • I can control the behaviour of any dependency that the class that I’m testing has
    • It enables me to test different paths of execution easily.
    • I can do proper unit testing, e.g. my tests have no dependency on databases, configuration files or other external resources

    Below is the OrderProcess class that I am going to use to demonstrate how to test using Rhino Mocks

        public class OrderProcess

        {

            private readonly IOrderRepository repository;

     

            /// <summary>

            /// Constructor

            /// </summary>

            /// <param name="repository"></param>

            public OrderProcess(IOrderRepository repository)

            {

                this.repository = repository;

                this.repository.OrderModified += new EventHandler(HandleOrderModified);

            }

     

            /// <summary>

            /// Applies a discount to an order if the

            /// order cost is greater than 1000

            /// </summary>

            /// <param name="orderId"></param>

            /// <returns></returns>

            public Order GetAndApplyDiscount(int orderId)

            {

                Order order = repository.Get(orderId);

     

                if (order != null)

                {

                    if (order.Cost > 1000)

                    {

                        order.Discount = 100;

                        repository.Persist(order);

                    }

                }

     

                return order;

            }

     

            /// <summary>

            /// Persists a list of orders

            /// </summary>

            /// <param name="orders"></param>

            public void Persist(List<Order> orders)

            {

                List<Order> newOrders = orders.Where(order => order.Id == 0).ToList();

                List<Order> existingOrders = orders.Where(order => order.Id > 0).ToList();

     

                if (newOrders.Count > 0)

                {

                    repository.Create(newOrders);

                }

     

                if (existingOrders.Count > 0)

                {

                    repository.Update(existingOrders);

                }

            }

     

            /// <summary>

            /// Deletes the specified order

            /// </summary>

            /// <remarks>Throws an OrderDeletionException is order deletion fails</remarks>

            /// <param name="order"></param>

            public void Delete(Order order)

            {

                try

                {

                    repository.Delete(order);

                }

                catch (Exception)

                {

                    throw new OrderDeletionException();

                }

            }

     

            /// <summary>

            /// Handles the OrderModified event

            /// </summary>

            /// <param name="sender"></param>

            /// <param name="e"></param>

            private void HandleOrderModified(object sender, EventArgs e)

            {

                //Code to handled the order modified event

            }

        }

    The OrderProcess class has a single dependency IOrderRepository which is shown below

        public interface IOrderRepository

        {

            event EventHandler OrderModified;

     

            Order Get(int Id);

     

            void Persist(Order order);

     

            void Delete(Order order);

     

            void Create(List<Order> orders);

     

            void Update(List<Order> orders);

        }

    The tests for the GetAndApplyDiscount method need to test the following cases

    • When the repository does not contain the order and returns  null
    • When the order returned by the repository has a order cost less than 1000
    • When the order returned by the repository has a order cost greater than 1000

    Below are the unit tests to satisfy the cases listed above

            /// <summary>

            /// Checks behaviour when order does not exist in the repository

            /// </summary>

            [TestMethod]

            public void GetAndApplyDiscount_When_Order_Does_Not_Exist()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

     

                repository.Stub(x => x.Get(25)).Return(null); //Order does not exist so return null

            

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

                Order output = objectToTest.GetAndApplyDiscount(25);

     

                //Assert

                repository.AssertWasNotCalled(x => x.Persist(Arg<Order>.Is.Anything)); //Make sure Persist was not called at all

     

                Assert.IsNull(output);

            }

     

    In the above test I’ve create a mock instance of the IOrderRepository to allow me to control its behaviour, next I have stubbed the IOrderRepository.Get method so that when it is called it returns null. Next I create an instance of the OrderProcess  class and call the GetAndApplyDiscount method, and finally I have asserted that the IOrderRepository.Persist method was not called.

     

            /// <summary>

            /// Check behaviour when discount should not be applied

            /// </summary>

            [TestMethod]

            public void GetAndApplyDiscount_When_Order_Cost_Less_Than_1000()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

     

                Order order = new Order {Cost = 750, Discount = 0};

                repository.Stub(x => x.Get(25)).Return(order); //Setup order to be returned by repository

     

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

                Order output = objectToTest.GetAndApplyDiscount(25);

     

                //Assert

                repository.AssertWasNotCalled(x => x.Persist(order)); //Make sure the order was not persisted

     

                Assert.AreEqual(0, output.Discount);

            }

     

            /// <summary>

            /// Checks behaviour when discount should be applied

            /// </summary>

            [TestMethod]

            public void GetAndApplyDiscount_When_Order_Cost_Greater_Than_1000()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

     

                Order order = new Order {Cost = 1200, Discount = 0};

                repository.Stub(x => x.Get(25)).Return(order); //Setup order to be returned by repository

     

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

                Order output = objectToTest.GetAndApplyDiscount(25);

     

                //Assert

                repository.AssertWasCalled(x => x.Persist(order)); //Make sure the order was persisted

     

                Assert.AreEqual(100, output.Discount); //Make sure the discount was added to the order

            }

    Below are the Persist method tests which verify the following cases

    • New orders are passed to the IOrderRepository.Create method
    • Existing orders are passed to the IOrderRepository.Update method

            /// <summary>

            /// Checks that the behaviour for persisting new orders

            /// </summary>

            [TestMethod]

            public void Persist_When_Orders_New()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

     

                List<Order> orders = new List<Order>

                                         {

                                             new Order {Id = 0, Cost = 1200, Discount = 0 },

                                             new Order{Id = 0, Cost = 1500, Discount = 0}

                                         };

     

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

                objectToTest.Persist(orders);

     

                //Assert

                repository.AssertWasCalled(x => x.Create(Arg<List<Order>>.List.ContainsAll(orders))); //Make sure orders were created

            }

     

            /// <summary>

            /// Checks the behaviour for existing orders

            /// </summary>

            [TestMethod]

            public void Persist_When_Orders_Already_Exist()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

     

                List<Order> orders = new List<Order>

                                         {

                                             new Order {Id = 2, Cost = 1200, Discount = 0 },

                                             new Order{Id = 12, Cost = 1500, Discount = 0}

                                         };

     

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

                objectToTest.Persist(orders);

     

                //Assert

                repository.AssertWasCalled(x => x.Update(Arg<List<Order>>.List.ContainsAll(orders))); //Make sure orders were updated

            }

     

            /// <summary>

            /// Checks the behaviour when there is a mix of new and existing orders

            /// </summary>

            [TestMethod]

            public void Persist_When_Mixture_Of_New_And_Existing_Orders()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

     

                Order order1 = new Order {Id = 2, Cost = 1200, Discount = 0};

                Order order2 = new Order {Id = 0, Cost = 1500, Discount = 0};

                Order order3 = new Order { Id = 32, Cost = 1200, Discount = 0 };

                Order order4 = new Order { Id = 0, Cost = 1500, Discount = 0 };

     

                List<Order> orders = new List<Order>

                                         {

                                             order1,

                                             order2,

                                             order3,

                                             order4

                                         };

     

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

                objectToTest.Persist(orders);

     

                //Assert

                repository.AssertWasCalled(x => x.Create(Arg<List<Order>>.List.ContainsAll(new List<Order>{order2, order4}))); //Make the sure correct orders were created

                repository.AssertWasCalled(x => x.Update(Arg<List<Order>>.List.ContainsAll(new List<Order> { order1, order3 }))); //Make the sure correct orders were updated

            }

    In the test above I’ve again mocked the IOrderRepository, then setup a list of orders (some of which are new and some which are existing) created an instance of the OrderProcess class passed the orders to the Persist method. I then assert that both the IOrderRepository’s Create and Update methods are called and verify that the correct orders are passed to each method

    Next are the tests for the Delete method which verify

    • That the IOrderRepository.Delete method is called
    • The OrderDeletionException is thrown if the IOrderRepository.Delete method throws an exception

            /// <summary>

            /// Checks behaviour when order is deleted

            /// </summary>

            [TestMethod]

            public void Delete_When_Order_Successfully_Deleted()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

     

                Order order = new Order();

     

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

                objectToTest.Delete(order);

     

                //Assert

                repository.AssertWasCalled(x => x.Delete(order)); //Make sure repository deletes the order

            }

     

            /// <summary>

            /// Checks behaviour when the repository throws an exception

            /// when deleting an order

            /// </summary>

            [TestMethod]

            [ExpectedException(typeof(OrderDeletionException))]

            public void Delete_When_Order_Deletion_Fails()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

                Order order = new Order();

     

                repository.Stub(x => x.Delete(order))

                    .Throw(new Exception("Deletion Failed")); //Throw an exception when repository is called

     

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

                objectToTest.Delete(order);

     

                //Assert

            }

    In the test above which verifies that an OrderDeletionException is thrown if the call to the IOrderRepository.Delete fails, I’ve stubbed the call to the Delete method so that when it is called an Exception is thrown and I’ve used the ExpectedException attribute to make sure the tests throws an OrderDeletionException.

    Finally I need to test that the OrderProcess class subscribes to the IOrderProcess’ OrderModified event as shown in the test below

            /// <summary>

            /// Checks that the order process subscribes to the

            /// OrderModified event

            /// </summary>

            [TestMethod]

            public void Constructor_Subscribes_To_OrderModified_Event()

            {

                //Arrange

                IOrderRepository repository = MockRepository.GenerateMock<IOrderRepository>(); //Create mock IOrderRepository so we can control its behaviour

     

                //Act

                OrderProcess objectToTest = new OrderProcess(repository);

     

                //Assert

                repository.AssertWasCalled(x => x.OrderModified += Arg<EventHandler>.Is.Anything); //Make sure that the OrderModified event has been subscribed to

            }

    Attached is an example project containing the code from this post.
Powered by Community Server (Personal Edition), by Telligent Systems