.NET and me Coding dreams since 1998!

29Oct/070

Acropolis Team Blog : Acropolis on the bench… P&P SCSF back on the field!

 Although I made a decision not to post any more news type of the post on my blog, this is something really exceptional.

I spent a lot of time in last year and a half learning CAB and SCSF and I was waiting till the May, 2007 SCSF v2 release so I could start doing a project I have on my mind for quite some time.

I've started working on it, but then in June Glenn Block announced death of SCSF. I was shocked, but after reviewing what Acropolis promised to offer I decided to sit tight and wait until spring 2008 and Acropolis release.

Today, on Acropolis team blog, they announced that they are moving Acropolis to "some future release" and that the good news is that P&P team announced working on "SCSF V3" - WPF composite client guidance.

I really have a lot of respect to the work P&P guys do and I spent already significant amount of time learning CAB related things, so on one way that is kind a good news for me, but on the other this really starts to make me very mad because I don't see the long term strong vision MS has on developing smart client applications.

At least P&P team makes more regular releases and iterations. I guess some of those releases would take some of the UI goodies from Acropolis and enhance the SCSF to be more DEV friendly.

The one thing which made me sad the most is I am still in learning mode regarding the WPF while Glenn is looking now for WPF experts to contribute. What a dream endeavor that is and I can not even think about it... Argh! :)

WPF Composite Client, it's coming!

Acropolis Team Blog : A new phase for the Acropolis project

Quote of the day:
The reason why so few good books are written is that so few people who can write know anything. - Walter Bagehot

Filed under: Uncategorized No Comments
25Oct/0716

Model View Presenter (MVP) design pattern close look – Part 1 (Supervising Controller)

 

Usually, usage of design patterns is associated with code executing in the lower tiers, but design patterns can be very usefully used in solving problems of the UI world too.

Two of my architecture blog posts are covering the examples related to patterns usage in solving the Web problems:

Although young,Model View Presenter pattern has been retired and two variations from original MVP pattern came up from it.

This little series of blog posts would cover in depth architecture and implementation of the both MVP design pattern successors: Passive View and Supervising Controller. All of the blog posts would use the same use case and the same Model domain entities, so the downsides and upsides of the different approaches can be easier notable.  

What is Model View Presenter?

If you are new to Model View Presenter pattern at all, you should check the Model View Presenter entry level post which explains the most important concepts of wiring the presenter and view in step by step manner. Once you would chew that, come back to this post and continue reading :)

  As we can see from this diagram:

  • View contains the Presenter instance (view "knows" presenter)
  • Presenter is the only class knowing how to reach to model and retrieve the data needed for performing business logic
  • Presenter talks to the View through the view interface (abstracted representation of the View without UI specific attributes)
  • View doesn't know nothing about the Model

View responsibility is to show the data provided by presenter, and purpose of the presenter is to reach to model, retrieve the needed data, performs required processing and returns the UI prepared data to the view.

The biggest difference between the Model View Controller (MVC) and Model View Presenter (MVP) pattern is in the fact that (in MVC) View is aware of model too.

I personally prefer more the MVP pattern because it leads to easier testability and decouples completely UI from the data sources, making it by that very testable.

Use case

Today's use case would be that we got request to build a simple web page which would allow us searching for a desired user and presenting its data retrieved from DB  on web page. User data which should be resented are: first name, last name and collection of his addresses. Web page is supposed to provide a way of informing the user when there is no user to be retrieved with a given use name.

UI interface should offer the possibility of editing the first name and last name data, but presenter should persist the data only if there would be some changes. In case UI didn't modify data retrieved from DB, presenter shouldn't make DB call at all.

The implementation design should allow testing the UI layer without using UI specific testing frameworks, preferably with most of the code logic extracted from a page level

Model

Both patterns today (passive view and supervising controller) would share the same model in their examples. Model for this use case would be represented with a component called UserRepositry which static class diagram looks something like this:

image

The User class is a domain data carrier class which has 4 properties.

Three of them are required to be presented to web page user:Name, Surname and Address where the Address is collection of UserAddress objects with City and Street properties.

Credit card number is user attribute which we don't want to present to web page user. It represents the example of domain attribute not required by UI.

The IUserService interface defines methods:

  • GetUser which for a given user name returns user object populated with appropriate retrieved data.
  • SaveUser which persist given user object

UserServiceStub is just a stub class stubbing the operation of user data retrieval from a database. I'm aware that  in unit tests I could use dynamic mock objects but for purpose of this blog post treat UserServiceStub as a class retrieving the data from a DB. The class itself implements IUserService like this:

   1: public class UserServiceStub:IUserService
   2: {
   3:     #region IUserService Members
   4:  
   5:     public User GetUser(string userName)
   6:     {
   7:         if (userName == "Nikola")
   8:         {
   9:             User newUser = new User();
  10:         
  11:             newUser.Name = "Nikola";
  12:             newUser.Surname = "Malovic";
  13:             newUser.Addresses.Add(new UserAddress("Vaclavske Namesti 11", "Prague, CZE"));
  14:             newUser.Addresses.Add(new UserAddress("5 Clock Tower", "Maynard, MA, USA"));
  15:             return newUser;
  16:         }
  17:         return null;
  18:     }
  19:  
  20:     public void SaveUser(User user)
  21:     {
  22:         // perform saving to DB
  23:     }
  24:  
  25:     #endregion
  26: }

In case that the given user name would be Nikola, the method would return user object with first name, last name and two addresses. In case of different user name the method would return null. Save method is just stubbing the functionality which saves the user data into the database

View markup

Both examples would share the same page html markup code definition which would look something like this:

   1: <div>
   2:     Enter desired user name:<asp:TextBox ID="SearchCriteriaTextBox" runat="server"></asp:TextBox>
   3:     <asp:Button ID="SearchButton" runat="server"  Text="Find user" OnClick="OnUserSearchButtonClicked" />
   4:     <br />
   5:     <asp:Label ID="ResultLabel" runat="server" />
   6:     <br />
   7:     <div id="resultPanel" runat="server" visible="false">
   8:         <asp:Label ID="FirstNameLabel" runat="server" text="First name" />
   9:         <asp:TextBox ID="FirstNameTextBox" runat="server" OnTextChanged="FirstName_TextChanged"  />        
  10:         <br />
  11:         <asp:Label ID="LastNameLabel" runat="server" text="Last name" />
  12:         <asp:TextBox  ID="LastNameTextBox" runat="server" OnTextChanged="LastName_TextChanged"/>        
  13:         <br />
  14:         <asp:Repeater ID="AdressesRepeater" runat="server">
  15:             <HeaderTemplate>
  16:                 <strong>Adresses</strong><br />
  17:             </HeaderTemplate>
  18:             <ItemTemplate>
  19:                 <%# Container.DataItem.ToString() %> <br />
  20:             </ItemTemplate>
  21:         </asp:Repeater>
  22:         <br />
  23:         <asp:Button ID="SaveButton" runat="server" Text="Save changes" OnClick="OnUserSaveButtonClicked" />
  24:     </div>
  25: </div>

On the top of the web form there is a SearchCriteriaTextBox  where the user would enter the user name of the user which data he wants to see. Once he would enter that, he would click on a SearchButton which click event would  be handled in OnSearchUser_Click event handler

ResultLabel purpose is to show the informative messages to web page user if there is no user with a given user name etc..

User data successfully retrieved  would be presented inside of the result pannel:

  • first name in FirstNameTextBox,
  • last name in LastNameTestBox
  • user addresses in repeateer called AddressRepeater

Inside of the result panel there is also Save changes button which click instantiates user persisting action

The page in design mode would look something like this:

image

Supervising controller

Supervising controller is a type of MVP design pattern based on a concept of data context binding where the view is implementing some "binding" logic on a object received from presenter which contains certain group of business data needed for the whole view. The view is therefore performing some functionality on it's own.

The biggest advantage of supervising controller is in the fact that presenter is not aware of the view internals, which allows reuse of one presenter with multiple views using the same context data source but with different UI elements. Also presenters are in general much simpler comparing with the Passive view presenters which need to take care about every single aspect of the view.

View interface

image

Interface contains next abstract representations:

  • label showing error messages is abstracted to StatusMessage - string setter property.
    Labels and in general other "read only" controls should be represented without getter, because user can not modify their value and therefore presenter is not interested in reading their value 
  • Find user button is abstracted to Search event represented with generic EventHandler<SearchEventArgs> delegate signature.
    SearchEventArgs is just an EventArgs using the additional SearchCriteria string property to carry the lookup criteria from the view to presenter on decoupled manner. Something like this:
    image
  • Save button is abstracted to a Save event argument with a default event argument signature
  • Last part of the view interface is a ContextData property. The purpose of this property is to behave as a "view data source".
    The communication between the presenter and the view is been done through that context data object
    Presenter is responsible to set the context data object value with values retrieved from the model and the view is supposed to update itself from that context data object value. View is also responsible to update appropriate context data properties with the values of the UI specific elements. Presenter then detects all the changes and updates the model with them.

View DTO (data transfer object)

Purpose of the DTO (Data transfer object) is to be information mule, without any logic inside which has a collection of properties in which data is carried in encapsulated manner. DTO pattern is essential one in implementing SOA systems, but I'll skip that aspect for now.

The biggest question related to View DTO is when we should use it at all? The downside of DTO is that we have to map domain object to the DTO which introduces one more level of indirection  ("There is no problem which can not be solved with one more level abstraction") and additional coding.

In our little example the IUserService.Get method returns the User object so why not pass that object to the view and skip the mapping hustle?
There are couple of cases which could be signals that the DTO mapping is required:

  1. User can be very heavy object which wouldn't be serialization optimal if we have distributed system scenarios
  2. In case of Active Record pattern based design it could expose some methods to the UI developer (user.Save()) which could confuse him or tempt him to make view code logic heavy avoiding presenter
  3. We need to present only a subset of the information domain object carries (in this example we don't need credit card information on UI level)
  4. We need to translate some of the strongly typed data to more "UI friendly" type of data. (In the example UserAddress type collection data would be translated to a collection of the strings so the repeater could perform easier data binding)

So, in this example UserDTO looking like this:

image

As we can see the DTO object has first name and last name string properties and collection of string addresses. There  is no credit card number property, because it is not required to be presented in UI.
IsDirty getter property is the property which value would be set to true if some of the property values would change. That value would be used for determining if the user data should be persisted or not

Data mapping

Data mapper design pattern default interpretation includes into the set of data mapper responsibilities beside mapping the data also the data retrieval activities. Although, I agree  that is the official and correct implementation, I don't like that small functional add on because it breaks the separation of concern principles. IMHO, purpose of the data mapper is just transformation of the already loaded data. Mapper should only know "how to map".

So, our little example therefore contains a DataMapper static helper class which class diagram looks like this:

image

We have overloaded Translate method which performs appropriate data translation for a given method parameter type

Let's take a quick look at the implementation of the first one

   1: public static UserDTO Translate(User user)
   2: {
   3:     UserDTO userDTO = new UserDTO();
   4:     userDTO.FirstName = user.Name;
   5:     userDTO.LastName = user.Surname;
   6:     userDTO.Addresses = MapUserAddress(user.Addresses);
   7:     return userDTO;
   8: }
   9:  
  10: private static IEnumerable<string> MapUserAddress(IEnumerable<UserAddress> adresses)
  11: {
  12:     foreach (UserAddress address in adresses)
  13:     {
  14:         yield return string.Format("{0},{1}", address.Street, address.City);
  15:     }
  16: }

This translate method accepts the User type instance as parameter.
In line 3, method creates the UserDTO instance and then maps the values of User instance properties to appropriate properties of UserDTO
In line 6, the method calls the user address collection mapping method which transform the collection of the UserAddresses into the IEnumerable<string> utilizing the yield c#

View implementation

Presenter - View wire up

The pattern used for establishing wire up between the view and presenter is dependency injection - constructor type.

The  key concepts of this wire up are:

  • presenter has a constructor accepting parameter of view interface type
  • view implements the view interface
  • view in page load constructs a presenter instance and throw himself to the presenter
  • presenter has a pointer then to the view, but the pointer type is view interface so presenter is not knowing nothing about the UI specific aspects of the view he's been injected
  • view keeps created instance of the pointer in the page field to support presenter method invocation in case of specific UI events

In code that would look like this:

   1: private UserDetailsPresenter _presenter;
   2:  
   3: protected void Page_Load(object sender, EventArgs e)
   4: {
   5:     // injecting the view into the presenter
   6:     _presenter = new UserDetailsPresenter(this);
   7: }

View interface implementation

The view is a web page implementing the view interface and wiring and mapping  the UI elements properties to the certain view interface members, something like this:

   1: #region IUserDetailsView Members
   2:  
   3: public UserDTO ContextData
   4: {
   5:     get { return Session["Context"] as UserDTO; }
   6:     set
   7:     {
   8:         Session["Context"] = value;
   9:         OnContextDataBound();
  10:     }
  11: }
  12:  
  13: public string StatusMessage
  14: {
  15:     set { ResultLabel.Text = value; }
  16: }
  17:  
  18: public event EventHandler<SearchEventArgs> Search;
  19: public event EventHandler<EventArgs> Save;
  20:  
  21: #endregion

In line 13, we implement the IView.StatusMessage property on a way that setting that property would end with setting the Web.UI.Label text property with the same value.

ContextData property implementation in this example stores a interface property value to a session variable (to prevent it from post backs) and calls the OnContextDataBound method where View would update itself with new context data, on a way similar to this:

   1: private void OnContextDataBound()
   2: {
   3:     FirstNameTextBox.Text = ContextData.FirstName;
   4:     LastNameTextBox.Text = ContextData.LastName;
   5:     AdressesRepeater.DataSource = ContextData.Addresses;
   6:     AdressesRepeater.DataBind();
   7:     resultPanel.Visible = true;
   8: }

So, in lines 3 and 4 we just set the text boxes text property with context object data values.
In line 5 and 6 code performs data binding to the collection of addresses context data
At the end, result panel is been presented to user.

View interface events  are implemented in lines 18 and 19, and they have just trivial event handlers to raise those events, something like this:

   1: protected void OnUserSearchButtonClicked(object sender, EventArgs e)
   2: {
   3:     if (Search != null)
   4:         Search(this, new SearchEventArgs(SearchCriteriaTextBox.Text));
   5: }
   6:  
   7: protected void OnUserSaveButtonClicked(object sender, EventArgs e)
   8: {
   9:     if (Save != null)
  10:         Save(this, new EventArgs());
  11: }

View routing logic is implementing the functionality of reflecting the UI specific changes to the appropriate context data object members.
Implementation could be trivial as the next code :

   1: protected void FirstName_TextChanged(object sender, EventArgs e)
   2: {
   3:     ContextData.FirstName = FirstNameTextBox.Text;
   4: }
   5:  
   6: protected void LastName_TextChanged(object sender, EventArgs e)
   7: {
   8:     ContextData.LastName = LastNameTextBox.Text;
   9: }

At the end of the view code implementation, the view needs to wire up itself with presenter (MVP diagram shows that view contains the instance of presenter) and we can do that by doing something like this:

   1: UserDetailsPresenter _userDetailsPresenter;
   2: protected void Page_Load(object sender, EventArgs e)
   3: {
   4:     // injecting the view into the presenter
   5:     _userDetailsPresenter=new UserDetailsPresenter(this);
   6: }

As we can see in line 5, the view constructs presenter instance and throws itself to the presenter constructor parameter so the presenter could have a pointer to the  view interface defined members.

Presenter

Class diagram of the presenter looks like this:

image

As we can see from the diagram, presenter has two public constructors and two private methods handling the appropriate view interface events. Presenter has also two fields which hold the presenter pointers to the view and service layers.

Presenter initialization

All the business logic of controlling,presenting and updating model and interaction with view should be encapsulated in the presenter. In this example Presenter is getting pointer to the view interface and model services through the utilization of constructor type of dependency injection design pattern.

   1: public UserDetailsPresenter(IUserDetailsView view, IUserService userService)
   2:  {
   3:      _view = view;
   4:      _userService = userService;
   5:      _view.Search += (OnUserSearch);
   6:      _view.Save += new EventHandler<EventArgs>(OnUserSave);
   7:  }
   8:  
   9:  public UserDetailsPresenter(IUserDetailsView view)
  10:      : this(view, new UserServiceStub())
  11:  {
  12:  }

I won't detail here too much about how DI works (if you need that, check out the Model View Presenter post) but summarized whatever the classes implementing the view and service interfaces would be, its pointers would be stored inside of the presenter object and the presenter would use them without having a knowledge what are the exact classes implementing the interfaces.

That's how the presenter would know only about the view interface (which abstracts the UI concepts) and not the view.

In line 5 and 6 we can see that the presenter is subscribing to the view save and search events.

The purpose of the first constructor is primary to enable appropriate unit testing of the presenter, but it won't be used in real world use cases. The reason why is like that lies in the fact that the view should be ignorant about the model in MVP pattern, so the view shouldn't know which model service class should inject to the presenter.

Second constructor is the one used by a view and we can se that it is enough for a view to pass a reference to itself  to a constructor and the Poor man dependency injection would occur in this(view, new UserServiceStub())  so the UserServiceStub instance pointer would be by default injected into the presenter.

One additional benefit of having those two constructors could be that the first one could be used (together with mocking) in implementing unit tests and the second one could be called in integration tests (where we need tests to talk with real, non mocked model representations like database for e.g.)

Presenter implementing view required logic

We have two methods in presenter which perform certain actions for a view, when view requests them.

We saw that to request something from a presenter the view would raise an event and due to the fact that presenter is in its constructor subscribing to the those events, when the view would send event presenter private method would be executed

NOTE: This is standard 'Fowler like' event based implementation of the view presenter  communication. The other (simpler) way how this could be implemented is that presenter could define as public methods implementing the logic required by a view and the view could directlly call them with something like: _presenter.OnUserSave() without having the need for defining events and related code concepts. The price of simplicity is that the presenter  broke his encapsulation from the view and that the view implementation is now tied to the specific presenter implementation. For a lot of people, this is fair trade off, so in my personal development I am implementing it like that.
The only reason why I am presenting it using events is to avoid comments that is "not by the book" and "too coupled" :)

OnUserSave method implementation

   1: private void OnUserSave(object sender, EventArgs e)
   2: {
   3:     if (_view.ContextData.IsDirty)
   4:     {
   5:         User user=new User();
   6:  
   7:         User domainUser = DataMapper.Translate(_view.ContextData);
   8:         _userService.SaveUser(domainUser);
   9:     }
  10: }
  11:  

In line 3, we see the presenter reads the context object IsDirty property value to determine if data is changed from the loaded data and if persisting is needed and if the IsDirty is true, in line 7 the DTO objects is been mapped (translated) to the domain type and the service persist method is called after

OnUserSearch method implementation

   1: private void OnUserSearch(object sender, SearchEventArgs e)
   2: {
   3:     if (string.IsNullOrEmpty(e.SearchCriteria))
   4:     {
   5:         _view.StatusMessage = "User name can not be null";
   6:         return;
   7:     }
   8:  
   9:     User user = _userService.GetUser(e.SearchCriteria);
  10:     if (user == null)
  11:     {
  12:         _view.StatusMessage = String.Format(
  13:             "There's no user found for user name:{0}", e.SearchCriteria);
  14:         return;
  15:     }
  16:  
  17:     UserDTO userDTO = DataMapper.Translate(user);
  18:     _view.ContextData = userDTO;
  19: }

In line 3 we examine the value of the event parameter caring the lookup user name data and in case of null or empty value in line 5 we set the view interface StatusMessage property value (which would cause on view level setting up the status message) to appropriate error message.

In line 9, presenter is accessing the Model through the UserService class GetUser method and in case of not existing user in line 12 sets the view interface message property to appropriate error message.

Finally, if a user is been successfully retrieved from a user service, presenter performs in line 17 mapping (translation) of the domain user data to the DTO type of user data which is then set to the interface view ContextData property (which would cause on view level OnDataBound method execution) 

Summary

Supervising Controller pattern is a UI design pattern which takes most complex responsibilities from the back of the web pages but still leaving them fair amount of autonomy. That makes it more suitable for implementing more complex UI pages/controls because having oversized presenter and undersized view can sometimes cause in teams overwhelming of developers working on presenter and leaves underused the one working on the view

Source code of today's example can be found here:  Supervising Controller source code

What is next?

Next part of the MVP close look post series would continue the MVP saga dissecting the Passive View variation of MVP pattern. Some of the classes and concepts presented in this post would be just referenced in i, so it would definitely be much shorter :)

Quote of the day:
Another such victory, and we are undone. - Pyrrhus

 

 

Share this post :

Filed under: Uncategorized 16 Comments
24Oct/071

Flavors of decorator pattern

GOF Decorator

 Armen Ayvazyan has a great blog post Decorator pattern where in great details explains the purpose and logic behind the GoF decorator pattern.

At the end of his example he uses the next static class diagram

Summarized: the Car is abstract class which is inherited by Toyota and Honda child specialized car classes and a Decorator abstract child class. Decorator class contains a field member of a Car type, which value is been injected through dependency injection (constructor type) and then use implementation over delegation to delegate its implementation of Car abstract methods to the injected instance stored in decorator field

Problem

There is no problem as long as inheritance relationship between the Decorator and Car is acceptable. But if we would like to inherit Decorator from some class different then the Car or we wouldn't like to decorate complete car we would have to do some variations in the decorator GoF implementation.

Generic Decorator

Generic decorator is based upon the inheritance implementation through the usage of Generics.

image

We would modify Decorator class to become an generic one and remove the inheritance from the Car class so it would look like this:

   1: public abstract class Decorator<TCar> where TCar:Car, new()
   2: {
   3:     private readonly TCar _car=new TCar();
   4:  
   5:     /// <summary>
   6:     /// Start the decorated car engine.
   7:     /// </summary>
   8:     public void Start()
   9:     {
  10:         _car.Start();
  11:     }
  12:  
  13:     /// <summary>
  14:     /// Drive the decorated car engine.
  15:     /// </summary>
  16:     public void Drive()
  17:     {
  18:         _car.Drive();
  19:     }
  20:  
  21: }

The modification on Decorator child/specialized classes would look like

   1: /// <summary>
   2: /// Decorates a car to be a taxi.
   3: /// </summary>
   4: public sealed class TaxiCar<TCar> : Decorator<TCar> where TCar : Car, new()
   5: {
   6:  
   7:     private int _passengers;
   8:     /// <summary>
   9:     /// Number of passengers per single day.
  10:     /// </summary>
  11:     public int Passengers
  12:     {
  13:         get { return _passengers; }
  14:         set { _passengers = value; }
  15:     }
  16: }

Notice that with generics we don't need any more to implement constructor based dependency injection of an Car instance

So the usage of the new decorated class would look like

   1: static void Main(string[] args)
   2: {
   3:     TaxiCar<Toyota> rc = new TaxiCar<Toyota>();
   4:     rc.Passengers = 3;
   5:     rc.Start();
   6:     rc.Drive();
   7:     
   8:     Console.ReadLine();
   9: }

Summarized: Courtesy of generics we can get the benefits of the decorator patterns without having inheritance limitations . Our taxi car is decorating the car without inheriting from it.

Interface based Decorator

That GoF implementation can be slightly  altered in case the base class implements some interface and we would like to decorate just behavior contracted with that interface but not the whole class. One more reason why we would like to do that is maybe because of the need that we would like our Decorator class to inherit from some class other then car, so the base decorator class could be enriched with the certain car attributes. This is the way to get the effect of multiple inheritance in C# I described  in my implementation over delegation post.

If we slightly alter the solution Armen explained by introducing the ICar interface , we would se that the solution he has would compile without the single line of code changed (outside of interface definition and defining its implementation by Decorator and Car classes).

So, the  decouple decorator taking whole functionality of the base class case could look like this

 image

Another example of the same idea of interface based decorator is that car would implement (beside ICar) an IParkable interface with the AutoPark method. In implementing  the TaxiCar I would like to "steal" the IParkable behavior of the car and decorate my taxi with it without "decorating" the behavior defined with the ICar.

Something like this.

image

 

Summary

Decorator is very powerful pattern which can be used for supplementing the inheritance relationship with composition based relationship. The basic idea stated in GoF is very flexible and it can be implemented on several different ways

I presented here how it can be done through  Interfaces and  Generics, but I'm sure there are some other ways it can be done more.

Quote of the day:
If the facts don't fit the theory, change the facts. - Albert Einstein

Share this post :

Filed under: Uncategorized 1 Comment
21Oct/079

TDD – Rhino Mocks – Part 2 – Some common scenarios

 

In first part of the Rhino Mock explorations, I've tried to give answers on what is mocking, what are the different recording modes available in Rhino mocks, how to set up some of results etc.

Today post would continue that by focusing on a few typical mocking tasks. To make this post easier to digest I've wrap those tasks into one "real world" example

Use case

ShoppingCart is class defining the Checkout method which is been called in the moment user wants to make a payment for the purchased items in the cart.
It has two properties: a) UserId - represents the id of the shopping cart user, b) CartAmount - represents the total amount to be charged to user for chosen cart items.

Shopping cart checkout process loads user data using a type implementing IUserRepository. Once user data are loaded, user bank account number is been used by a type implementing the IPaymentProcessor  interface and then if a user has enough funds on his account, cart sends directs payment to payment processor type.

Once the payment would be successfully processed in payment processor, payment processor would raise an event which would signalize the cart that the payment is been completed.  When that would happen cart should store the payment in user payment history and reset the cart value to zero

 

Considering the mentioned use case, we could be testing next things:
1) In case user repository couldn't find an user for a given user id, cart should throw argument exception
2) We need to verify that once payment processor raised an event and signalized that the payment is completed the cart value would be reset to zero and the user repository would add that payment to payment history
3) In case payment attempt would failed due to time out, cart component should recover gracefully and the cart value should stay untouched
4) In case user is having less money on account then the cart value, the payment method should not be called and the cart amount should stay unchanged
5) We need to verify that the performance is optimal by verifying that the retrieving of user data occurred only once

Shopping cart static class diagram

Shopping cart class diagram

As we can see from the class diagram shopping cart uses constructor type of dependency injection design pattern to get pointers to instances of types implementing the IUserRepository and IPaymentProcessor which are then used in checkout method. PaymentSucceed method is a event handler  which handles PaymentSucceed event of the Payment processor.

Although I prefer black box testing approach, we would take a peek at the shopping cart implementation because purpose of this post is not TDD test first methodology, but mocking examples

Checkout method

 

   1: public void Checkout()
   2: {
   3:     User user = _userRepository.GetUser(UserName);
   4:     if (user == null)
   5:         throw new ArgumentException();
   6:  
   7:     double bankBalance = _paymentProcessor.GetBankBalance(user.BankAccount);
   8:     bool userHasEnoughMoney = bankBalance > Amount;
   9:     if (userHasEnoughMoney)
  10:     {
  11:         double oldAmount = Amount;
  12:         try
  13:         {
  14:             _paymentProcessor.MakePayment(user.BankAccount);
  15:         }
  16:         catch (TimeoutException e)
  17:         {
  18:             // logger.Error("Payment time out", e);
  19:             Amount = oldAmount;
  20:         }
  21:     }
  22: }

The method first retrieves the user for a given user name. Then, user bank balance amount is been retrieved  and in case of user having enough money on his account, payment is been made

PaymentSucceed method

   1: void PaymentSucceed(object sender, EventArgs e)
   2: {
   3:     _userRepository.AddToUserPaymentHistory(UserName, Amount);
   4:     Amount = 0;
   5: }

A PaymentSucceed event would be processed by adding user payment history information and resetting cart amount to zero

Test 1. How to define expectations on a method accepting unknown parameters

Rhino Mock concepts: IgnoreArguments()

In case user repository couldn't find an user for a given user id, cart should throw argument exception

Test purpose

Purpose of this test is to verify that if a GetUser would get ANY argument which would cause returning of the null user value, shopping cart checkout method should throw an argument exception

Test code

   1: [Test]
   2: [ExpectedException(typeof(ArgumentException))]
   3: public void Checkout_Verify_That_NotKnownUser_Throws_ArgumentException()
   4: {
   5:     //setting up the stage - retrieval of the user would return null
   6:     Expect.Call(_userRepository.GetUser(null))
   7:         .IgnoreArguments()
   8:         .Return(null);
   9:  
  10:    //stop recording
  11:     _mockRepository.ReplayAll();
  12:  
  13:     ShoppingCart cart = new ShoppingCart(_user.Name, _userRepository, _paymentProcessor, 0);
  14:     cart.Checkout();
  15: }

Test interpretation

In line 6 we define that we expect someone would call  the GetUser method, but because our test is not specific to any constrain related to user name we are passing the null value as the expected userId parameter value but in line 7 we use the IgnoreArguments() method which commands the Rhino Mock framework to disregard what parameters are exactly used as previous method parameters.  In line 8, I've defined that the method would return null value.
Result of lines 6 , 7 and 8 could be read as something like "expect that there would be a call to GetUser method with some unknown parameter for which UserRepository would return null value as result".

Line 11 stops recording mode and line 14 calls the checkout method

Now, if we would take a look at line 3 in Checkout method code snippet we would see that expected call for retrieving user happened and Rhino Mock returned defined null value as result. That null value caused ArgumentException to be thrown in line 5 which is what this test was expecting.

Test 2. How to simulate event raising of mocked object

Rhino Mock concepts: LastCall, IgnoreArguments(), GetEventRaiser(), IEventRaiser

We need to verify that once payment processor raised an event and signalized that the payment is completed the cart value would be reset to zero and the user repository would add that payment to payment history

Test purpose

This test describes:
- how NUnit assert can be used on the non mocked object to verify that mocks made desired effect on it
-  how to simulate event raised on the mock

Test code

   1: [Test]
   2: public void Checkout_Verify_That_Successfull_CheckOut_Would_Make_Cart_Value_Zero()
   3: {
   4:     double cartAmount = 100;
   5:  
   6:     //setting up the stage 
   7:     // 1. Regular user with default data would be retrieved
   8:     Expect.Call(_userRepository.GetUser(_user.Name))
   9:         .Return(_user);
  10:  
  11:     //2. User would have enough money on his account for payment
  12:     Expect.Call(_paymentProcessor.GetBankBalance(_user.BankAccount))
  13:         .Return(cartAmount + 1);
  14:  
  15:     // 3. geting the payment proccessor payment succeed event raiser 
  16:     // which we would use to simulate the async signal that the payment is complete
  17:     _paymentProcessor.PaymentSucceed += null;
  18:     IEventRaiser paymentSucceedEventRaiser = LastCall.IgnoreArguments().GetEventRaiser(); 
  19:  
  20:     // 4. Expect that successfull payment would be stored in user payment history
  21:     _userRepository.AddToUserPaymentHistory(_user.Name, cartAmount);
  22:  
  23:     //stop recording
  24:     _mockRepository.ReplayAll();
  25:  
  26:     ShoppingCart cart = new ShoppingCart(_user.Name, _userRepository, _paymentProcessor, cartAmount);
  27:     cart.Checkout();
  28:     // we now simulate payment suceed event send from payment processor 
  29:     paymentSucceedEventRaiser.Raise(_paymentProcessor,new EventArgs());
  30:     // checking if the cart amount is zero
  31:     Assert.IsTrue(cart.Amount.Equals(0), "Cart amount to be paid not reset to zero.");
  32: }

Test interpretation

This test does next things:

  • in line 8,  we define that the call to GetUser method would return the default user
  • in line 12, we define that user has on his account amount of money greater then the cart amount
  • in line 17, we define expectations that some event handler (null value) would register to the PaymentSucceed event
  • in line 18, we use the LastCall class which is a helper class which points to the last recorded command in the Rhino Mock command stack.
    We can treat that LastCall as "pointer to L17", so the method IgnoreArguments()  can be read as "the null value as subscriber to the PaymentSucceed should be replaced with 'some event handler'".
    Executing GetEventRaiser() method on 'redefined' L17 results with a pointer to PaymentSucceed event which is stored in type implementing the IEventRaiser
  • In line 21, we define expectation that the payed amount would be added to the user payment history
  • in line 24, we stop recording expectations
  • in line 27, we call the checkout method of the shopping cart with valid payment context which should result with completion of the payment
  • In line 29, we use the event pointer retreived in L18 to simulate PaymentSucceed event raising by the PaymentProcessor as the result of successful payment
  • In line 31, we check that the cart value

 

Test 3. How to simulate exception throwing of mocked object

Rhino mock concepts: LastCall, Throw

In case payment attempt would failed due to time out, cart component should recover gracefully and the cart value should stay untouched

Test purpose

This test describes two things:
a) it explains LastCall mechanism for handling void returning methods in Rhino Mocks
b) it explains how to simulate mocked object throwing an exception scenario

Test code

   1: [Test]
   2: public void Checkout_Verify_That_In_Case_Of_Payment_Timeout_Cart_Value_Would_Stay_Unchanged()
   3: {
   4:     double cartAmount = 100;
   5:  
   6:     //setting up the stage 
   7:     
   8:     // 1. Regular user would be retrieved
   9:     Expect.Call(_userRepository.GetUser(_user.Name))
  10:         .Return(_user);
  11:  
  12:     //2. Account check would return information that user is having enough money
  13:     Expect.Call(_paymentProcessor.GetBankBalance(_user.BankAccount))
  14:         .Return(cartAmount + 1);
  15:  
  16:     _paymentProcessor.MakePayment(_user.BankAccount);
  17:     LastCall.Throw(new TimeoutException("Pament failed. Please try later again."));
  18:  
  19:     //stop recording
  20:     _mockRepository.ReplayAll();
  21:  
  22:     // cart amount is less then user account balance
  23:     ShoppingCart cart = new ShoppingCart(_user.Name, _userRepository, _paymentProcessor, cartAmount);
  24:     try
  25:     {
  26:         cart.Checkout();
  27:         Assert.IsTrue(cart.Amount == cartAmount, "Cart amount is changed altought there was timeout roolback scenario");
  28:     }
  29:     catch (TimeoutException)
  30:     {
  31:         Assert.Fail("Checkout procedure didn't recover gracefully from timeout exception");
  32:     }

Test interpretation

This test does next things:

  • in line 9  we define that the call to GetUser method would return the default user
  • in line 13, we define that user has on his account amount of money greater then the cart amount
  • in line 16, we define expectations that the MakePayment method of the mocked payment processor would be called with a user bank account.
    We are not using Expect.Call(_paymentProcessor.MakePayment(_user.BankAccount)) because that is not applicable to the methods returning void value due to the limitations of the C#
  • in line 17, we go around the C# limitation related to void methods and use the LastCall class which is a helper class which points to the last recorded command in the Rhino Mock command stack.
    So the result of LastCall would be pointer to L16
  • in line 17, once we would have a pointer defined with LastCall we use a Throw method to get "MakePayment method execution in L16 would throw an TimeoutException"
  • in line 20, we stop recording expectations
  • In line 26, we trigger the checkout method execution (which would receive TimeoutException defined in L17
  • In line 27 we verify that the cart value stayed unchanged after the TimeoutException occured
  • In line 29, we catch the TimeOutExcpetion and make assertation failing because if that woudl happen that would mean that the cart checkout method didn't recover gracefully from exception so the exception bubbled up outside of the checkout method

Test 4. How to verify that some method of the mocked object was never called

Rhino mock concepts: Repeat.Never

In case payment attempt would failed due to time out, cart component should recover gracefully and the cart value should stay untouched

Test purpose

This test describes:

-usage of Repeat.Never() for testing that some method WAS NOT executed in certain scenario

Test code

   1: [Test]
   2: public void Checkout_Verify_That_User_Without_Enough_Money_Cant_Complete_CheckOut()
   3: {
   4:     double cartAmount = 100; 
   5:  
   6:     //setting up the stage 
   7:     // 1. Regular user would be retrieved
   8:     Expect.Call(_userRepository.GetUser(_user.Name))
   9:         .Return(_user); 
  10:  
  11:     //2. Account check would return information that user is having enough money
  12:     Expect.Call(_paymentProcessor.GetBankBalance(_user.BankAccount))
  13:         .Return(cartAmount - 1); 
  14:  
  15:     //expectation: MakePayment won't be called because user is not having enough money on account
  16:     _paymentProcessor.MakePayment(null);
  17:     LastCall.IgnoreArguments()              /* we don't care which user id should be used */
  18:         .Repeat.Never();                    /* We expect zero method execution*/ 
  19:  
  20:     //stop recording
  21:     _mockRepository.ReplayAll(); 
  22:  
  23:     // cart amount is +1 then user account balance
  24:     ShoppingCart cart = new ShoppingCart(_user.Name, _userRepository, _paymentProcessor, cartAmount);
  25:     cart.Checkout();
  26:     Assert.IsTrue(cart.Amount == cartAmount, "Cart value was modified event the payment was not made");
  27: }
  28:  

This test does next things:

  • in line 8 ,  we define that the call to GetUser method would return the default user
  • in line 12, we define that user has on his account amount of money LESSER then the cart amount is (user is not having enough money to pay)
  • in line 16, we define expectations that the MakePayment method of the mocked payment processor would be called with a null value as user bank account.
    The reason why we pass a null value is that this method shouldn't be called at all in this scenario so it is totally irrelevant what user id would be passed
  • in line 17, we use the LastCall class which is a helper class which points to the last recorded command in the Rhino Mock command stack, which is in this case L16
  • in line 18, we define expectation that the method would be called exactly zero time == expectation that the method won't be called.
    If the method which expectation is defined with Repeat.None would be called, the test would fail
  • in line 21, we stop recording expectations
  • in line 25 ,we call the cart checkout method
  • in line 26, we verify that the cart value is not modified in use case of payment not made

Test 5. How to verify that performance are optimal

Rhino mock concepts: Repeat.Once combined with CreateMock mockery method

We need to verify that the performance is optimal by verifying that the retrieving of user data occurred only once

Test purpose

This test describes:

- Repeat.Once - How to test performance related things such as lazy load

Test code

   1: [Test]
   2: public void Checkout_Verify_That_Retreving_Of_User_Data_Occured_Only_Once()
   3: {
   4:     double bankBalance = 100;
   5:     double cartAmount = bankBalance - 1;
   6:  
   7:     //setting up the stage 
   8:     Expect.Call(_userRepository.GetUser(_user.Name))
   9:         .Return(_user)
  10:         .Repeat.Once();
  11:  
  12:     //stop recording
  13:     _mockRepository.ReplayAll();
  14:  
  15:     // cart amount is +1 then user account balance
  16:     ShoppingCart cart = new ShoppingCart(_user.Name, _userRepository, _paymentProcessor, cartAmount);
  17:     cart.Checkout();
  18: }

This test does next things:

  • in line 8 and 9, we define expectation that the user repository would return default user data
  • in line 10, we constrain that expectation with expectation that the method would be called exactly once.
    This simple constrain is a way how to test lazy loads and similar things
  • in line 13, we stop recording expectations
  • in line 17, we call the cart check out method

 

Test 6. How to customize failed expectation messages 

Rhino mock concepts: Message

Test purpose

This test describes:

- Rhino mock Message method purpose

This test would be the only one failing so we could see the error message

Test code

   1: [Test]
   2: public void Checkout_Verify_That_Retreving_Of_User_Data_Occured_Twice()
   3: {
   4:     //seting up the stage 
   5:     Expect.Call(_userRepository.GetUser(_user.Name))
   6:         .Return(_user)
   7:         .Repeat.Twice()
   8:         .Message("Retrieving of the user did not occurred twice");
   9:  
  10:     //stop recording
  11:     _mockRepository.ReplayAll();
  12:  
  13:     // cart amount is +1 then user account balance
  14:     ShoppingCart cart = new ShoppingCart(_user.Name, _userRepository, _paymentProcessor, 0);
  15:     cart.Checkout();
  16: }

This test does next things:

  • in line 5 and 6, we define expectation that the user repository would return default user data
  • in line 7, we constrain that expectation with expectation that the method would be called exactly twice.
    We saw in previous test that expectation won't be met and this expectation failure would cause test failure
  • in line 8, we define what would be the message which would be outputted if the expectation would fail
  • in line 11, we stop recording
  • in line 15, we call cart checkout method

This test would fail with message

Rhino.Mocks.Exceptions.ExpectationViolationException: Message: Retrieving of the user did not occurred twice
IUserRepository.GetUser("Nikola"); Expected #2, Actual #1.

Conclusion

I believe this couple of examples of how easy and intuitive rhino mock usage is would encourage all the mock sceptics to try use them and TDD development process

I plan to continue posting about Rhino mocks in upcoming days, providing the real world answers on real world type of questions one may have about Rhino mocks

Source code of today's example can be found: here.

 

 

 

Share this post :

Filed under: Uncategorized 9 Comments