Geeks With Blogs
Blog Moved to http://podwysocki.codebetter.com/ Blog Moved to http://podwysocki.codebetter.com/
For the past couple of years, the Model View Presenter pattern has gotten a lot of attention on the .NET platform and more in particular to ASP.NET.  For a thorough introduction on MVP with ASP.NET, read the article on CodeProject by Billy McCafferty.

Recently, it has come to play that many now favor the Model View Controller (MVC) pattern over MVP.  If you're confused about the differences between the two, check out this post which will explain it well.  The basic gist is that the MVP pattern gives you the ability to mock the view whereas the MVC pattern allows for the mocking of the entire flow, including the context, request and response.  To me, that's a bit of overkill right now for what I need with SharePoint, especially when dealing with Web Parts.

Now the term Model View Presenter (MVP) itself has been retired now for a year by Martin Fowler and split into two new patterns.  It has been split into two parts:
So, what's the difference between the two and which to pick?

The Supervising Controller

The Supervising Controller uses a controller to both handle the input response but also manipulate the view to handle the complex view logic.  The view is left to simple behavior, only intervening when it cannot be done in the controller.  The presentation functionality is split into two parts, the presenter and the view.  The model is separate for this design pattern. 

The Supervising Controller has two main responsibilities:  input response and view/model synchronization.  For input response, the controller operates in the presenter style.  All actions on the screen are handed off to the presenter which in turn handles all the logic.  For the view/model synchronization, the controller relegates much of that functionality to the view.  The view uses the typical data binding for populating the data fields.

The Passive View

The Passive View reduces the behavior of the UI components to a minimum by using a controller/presenter that not only handles the responses to events, but also handles the updating of the view.  This allows for easier testing to be focused mostly on the controller/presenter and not as much on the view.

With this pattern, the user interface is split into two parts, the view that handles the display and the controller that responds to user actons.  The change from the typical MVP pattern is that the view is completely passive and no longer responsible for updating itself from the model.  All of the view logic is contained in the controller/presenter and there is no dependency in either direction between the view and the model.

Moving Into SharePoint

There are two different ways to approach this problem as noted above, either the Supervising Controller or the Passive View.  For this post, let's go with the Passive View approach.  In this example, I will be creating a random quote generator web part part .  So, let's define the view first.

public interface IRandomQuoteView
{
     // Quote related fields
     string QuoteCategory { get; }
     string Quote { set; }
    
     // Status message for errors
     string StatusMessage { set; }
}

As defined above, we need to get the values in our presenter from the view for our random quote generator  The presenter is responsible for setting the StatusMessage which indicates whether it passed or failed validation as well as the quote itself.  Pretty simple, eh?  Now let's go ahead and define the presenter.  Remember that we need to connect to a business layer/data layer and will have dependency injection for loose coupling and separation of concerns.

public class RandomQuotePresenter
{
     private readonly IQuoteService quoteService;
     private readonly IRandomQuoteView quoteView;

     public RandomQuotePresenter(IRandomQuoteView quoteView) : this(quoteView, new SharePointQuoteService()) {}

     public RandomQuotePresenter(IRandomQuoteView quoteView, IQuoteService quoteService)
     {
          this.quoteView = quoteView;
          this.quoteService = quoteService;
     }

     public void InitView()
     {
          if(string.IsNullOrEmpty(quoteView.QuoteCategory))
          {
               quoteView.StatusMessage = "Category required";
               return;
          }

          try
          {
               quoteView.Quote = quoteService.GetRandomQuote(quoteView.QuoteCategory);

               if(string.IsNullOrEmpty(quoteView.Quote))
                    quoteView.StatusMessage = "No Quote Found...";
          }
          catch(QuoteServiceException)
          {
               quoteView.StatusMessage = "Data error";
          }
     }
}

Ok, now that we have the presenter created, let's start testing.  Well, actually I should have stubbed everything out first and then made it fail, then make it pass, but let's continue.  Let's do some unit testing on this piece.  I'll be using Rhino Mocks as always to do my mocking.

[Test]
public void NullQuoteCategoryShouldCauseCategoryRequiredMessage()
{
     MockRepository repository = new MockRepository();
     IQuoteService service = repository.CreateMock<IQuoteService>();
     IRandomQuoteView view = repository.CreateMock<IRandomQuoteView>();
     Expect.Call(view.QuoteCategory).Return(null);
     view.StatusMessage = "Category required";
     RandomQuotePresenter presenter = new RandomQuotePresenter(view, service);
     repository.ReplayAll();

     presenter.InitView();
     repository.VerifyAll();
}

Well, that was easy, and we didn't even need a UI to do it.  Well, now let's bring SharePoint web parts into the game.

[Guid("357b9668-0f88-4bcb-87a2-c34cc6694e90")]
public class RandomQuoteWebPart : WebPart, IQuoteOfTheDayView
{
     private
RandomQuotePresenter presenter;

     private string quoteCategory;
     private string quote;
     private string statusMessage;

     public string QuoteCategory { get { return quoteCategory; } }

     public string StatusMessage { set { statusMessage = value; } }

     public string Quote { set { quote = value; } }

     [WebBrowsable, Personalizable]
     public string QuoteCategoryType
     {
          get { return quoteCategory; }
          set { quoteCategory = value; }
     }

     protected override void OnLoad(EventArgs e)
     {
          presenter = new RandomQuotePresenter(this);
          presenter.InitView();
     }

     protected override void Render(HtmlTextWriter writer)
     {
          writer.write("Quote Category: " + quoteCategory + "<br/>");
          writer.write("Quote: " + quote + "<br/>");
          if(!string.IsNullOrEmpty(statusMessage))
               writer.write("Status Message: " + statusMessage);
     }
}

Sure, I'm simplifying it a bit, but you get the general idea.  I'm persisting the QuoteCategory as something configurable through a web part.  The rest comes as natural as a standard web part on how to render.  The OnLoad is where the magic happens with talking to the presenter to set up the view.  Pretty cool, huh?  The key is to keep your view as simple as possible and let the presenter do the work for you.

So, is that all that's to it?  Well, not really...  As you may have noted, my data service really comes from SharePoint, and moreover, a SharePoint list.  Let's talk about that now...

Mocking Out SharePoint

As most web developers know, unit tests can be hard for web applications that have dependencies on such things as the HttpContext, etc.  Well, in the SharePoint world, it's no different.  So, what options do we have to stub out, say the SPContext, SPList and so on so that we're not tightly coupled to the API for our unit tests?  It's not super easy due to the fact that there are static members, so interfaces won't suffice there.

We have the following options:
  • Write interfaces and wrappers for each SharePoint object
  • Use Duck Typing to create the interfaces and cast the SharePoint objects to them
  • Use TypeMock.NET to create a recorder and play back
  • Use Reflector Add-in Doubler to create our test doubles
Let's look at each one.

Wrap each object

In the worst case scenario, you can write all the interfaces for all the classes you wish to mock and create doubles for each by hand.  This includes defining the interface for SPContext, SPList, SPWeb, SPSite and the actual implementations.  This is not hard, but time consuming and prone to error when dealing with this much code.  Not the ideal situation

Duck Typing

Duck Typing itself is not a new concept.  This allows you to infer the functionality through interfaces.  Duck Typing is available for .NET through the Duck Typing Project.  This is more apt for dynamic languages such as Ruby, but let's give it a try here for a SharePoint object.

interface ISPField
{
     object GetFieldValue(string value);
     object GetFieldValueAsHtml(object value);
     // And so on
}

public void ConsumeField(ISPField field)
{
     ...
}

And in my calling code:

SPField field = // Get field
ISPField iField = DuckTyping.Cast<ISPField>(field);
ConsumeField(iField);

Phil Haack has more on the subject here.

TypeMock.NET

Rhino Mocks has a limitation, as do most mocking frameworks of only being able to mock interfaces and abstract classes.  Well, SharePoint has that limitation due to all classes being concrete and/or sealed.  Enter TypeMock.NET which allows you to record just about any object in the .NET Framework just as if it were the real thing.  This allows for mocking of even static members which is something that the others cannot do.  Of course this product comes with a price tag, depending on your organization.  Another point to make is that it really isn't "abstracting" away your dependencies at all, it's just masking them.  I've seen pluses and minuses about it and I just haven't made up my mind yet.

In order to do some mocking, there are some good samples out there including this one on HttpContext using TypeMock.NET.

Doubler

Now let's look at the final one.  Doubler is a .NET Reflector Add-in developed by Jay Flowers.  The intent of this add-in is to generate code for unit tests, wrappers and stubs. 

Install this add-in and simply right-click on any class and you get the following options:
  • Recording Generator
  • Wrapper/Interface Generator
  • Test Generator
  • Fake Generator
  • Call Graph
Pretty cool stuff and it just works.  This is a highly recommended product for generating your stubs.

Wrapup

Well, this has been a pretty long post on doing development with SharePoint and I hope it helps.  There are many hurdles to overcome for doing good design and testing with SharePoint, but I hope this leads in the right direction.

Where do we go from here?  Well, we can start looking at IoC containers for our dependency injection for our presenter, we can look at using the Supervising Controller and so on.  Plenty of opportunities to explore!

Develop, mentor and inspire!

kick it on DotNetKicks.com
Posted on Thursday, December 20, 2007 1:11 PM Microsoft , SharePoint , .NET , Test Driven Development | Back to top


Comments on this post: Model View Presenter (MVP) Passive View, SharePoint and Mocking

# re: Model View Presenter (MVP) Passive View, SharePoint and Mocking
Requesting Gravatar...
Great post Matt! We're using mostly Passive View MVP in our TrainingManagement sample app. We're also using Typemock Isolator to mock out SharePoint API calls.

I found it difficult using Doubler when dealing with SharePoint classes with deep property heirarchies (e.g. SPContext.Current.Web.Lists.Item). Did you experience this too?
Left by Francis Cheung on Sep 08, 2008 5:40 PM

# re: Model View Presenter (MVP) Passive View, SharePoint and Mocking
Requesting Gravatar...
I solved the deep property hierarchies with a dependency injection approach.

Also,
with a little coding you can make your own mock-able sharepoint dll with Mono.Cecil. (http://jaredlobberecht.blogspot.com/2008/10/mocking-microsoft-sharepoint-2007.html)
Left by Jared on Oct 19, 2008 8:40 PM

Your comment:
 (will show your gravatar)


Copyright © Matthew Podwysocki | Powered by: GeeksWithBlogs.net