Bookmark and Share    Narrow width layout Medium width layout Full-screen width layout    Small text Medium text Large text    Color Palette Selector    Thursday, March 11, 2010
    
    Extra » RSS » DNN Blogs RSS Loadtime: 0.7968597 sec.
Register  Login  
 DNN Blog RSS Minimize

This article is cross-posted from my personal blog.

A year or so ago I wrote a series of blog posts about building testable modules using the Model-View-Presenter (MVP) pattern.  The MVP pattern of development provides many of the benefits attributed to the Model-View-Controller (MVC) pattern, which has become very popular recently as an alternative approach to ASP.NET development. 

You can have your cake and eat it too.

Its main strength though is that it retains most of the benefits of the WebForms Framework of rich controls, with which we are familiar. 

The MVP pattern achieves this by requiring the View (usually a UserControl or Page)which receives control from the WebForms Framework to pass “control” to a Presenter class, and it requires a good deal of discipline from developers to ensure that the pattern is followed. 

The pattern also requires developers to “wire-up” the three classes View, Presenter and Model (or ViewModel) every time they need a new control (or View).

This degree of complexity has tended to hamper the use of the MVP pattern, as it requires much more work on the part of developers in general (and module developers in particular).

I am pleased to announce that in the next public release of DNN (version 5.3) we will be including a set of base classes that provide most of this wiring-up out-of-the-box. 

This new framework is based on a fairly new Codeplex project WebFormsMVP from Tatham Oddie (of Readify in Australia) and Damian Edwards (formerly of Readify, but now assimilated by the Borg (Microsoft)).  Many of you will know that Phillip Beadle a long-time DNN Community member and now DNNCorp Employee also used to work at Readify.

We had already decided to add MVP support for module development in this development cycle and after meeting with Damian and Tatham at the recent MVP (as in Microsoft Most Valuable Professional) summit in Redmond, we decided to replace our MVP (Model-View-Presenter) code with their Library, which was much more advanced, and was licensed under a compatible Open Source license.  Tatham and Damian have used the WebFormsMVP framework on a number of high-profile websites in Australia so it is well-tested

Move over PortalModuleBase – Hello ModulePresenter and ModuleView

In order to take as much advantage as we can from this new framework we have built a thin layer on top of their code to ensure that the Presenters and Views all know about Module Context and Portal Settings. 

Two new modules that we will be delivering as part of the 5.3 release have been built on this new framework and will showcase how to use the framework and how to write tests at every layer of the application.

In addition, I will blog in future article(s) on how you can use this new framework to create testable modules of your own.

This article is cross-posted from my personal blog.

A year or so ago I wrote a series of blog posts about building testable modules using the Model-View-Presenter (MVP) pattern.  The MVP pattern of development provides many of the benefits attributed to the Model-View-Controller (MVC) pattern, which has become very popular recently as an alternative approach to ASP.NET development. 

You can have your cake and eat it too.

Its main strength though is that it retains most of the benefits of the WebForms Framework of rich controls, with which we are familiar. 

The MVP pattern achieves this by requiring the View (usually a UserControl or Page)which receives control from the WebForms Framework to pass “control” to a Presenter class, and it requires a good deal of discipline from developers to ensure that the pattern is followed. 

The pattern also requires developers to “wire-up” the three classes View, Presenter and Model (or ViewModel) every time they need a new control (or View).

This degree of complexity has tended to hamper the use of the MVP pattern, as it requires much more work on the part of developers in general (and module developers in particular).

I am pleased to announce that in the next public release of DNN (version 5.3) we will be including a set of base classes that provide most of this wiring-up out-of-the-box. 

This new framework is based on a fairly new Codeplex project WebFormsMVP from Tatham Oddie (of Readify in Australia) and Damian Edwards (formerly of Readify, but now assimilated by the Borg (Microsoft)).  Many of you will know that Phillip Beadle a long-time DNN Community member and now DNNCorp Employee also used to work at Readify.

We had already decided to add MVP support for module development in this development cycle and after meeting with Damian and Tatham at the recent MVP (as in Microsoft Most Valuable Professional) summit in Redmond, we decided to replace our MVP (Model-View-Presenter) code with their Library, which was much more advanced, and was licensed under a compatible Open Source license.  Tatham and Damian have used the WebFormsMVP framework on a number of high-profile websites in Australia so it is well-tested

Move over PortalModuleBase – Hello ModulePresenter and ModuleView

In order to take as much advantage as we can from this new framework we have built a thin layer on top of their code to ensure that the Presenters and Views all know about Module Context and Portal Settings. 

Two new modules that we will be delivering as part of the 5.3 release have been built on this new framework and will showcase how to use the framework and how to write tests at every layer of the application.

In addition, I will blog in future article(s) on how you can use this new framework to create testable modules of your own.

We-Want-You As I indicated last week, I am pleased to announce the Call for Speakers for the 2010 DotNetNuke Connections conference.  Once again, this years conference will be held at the Mandalay Bay in Las Vegas from November 1st through the 4th with pre and post-conference training available as well. 

We could not do this show without our speakers and we have been fortunate in the past to have had some great session proposals by many well respected speakers.  Some of those speakers have been selected to present their sessions and unfortunately some of them have not been.  Such is the nature of any conference.  As usual we will continue to look for new speakers to bring fresh new topics to the conference.  So if you have submitted sessions in the past then I would encourage you to submit again.  If you have public speaking experience and some great ideas for sessions then I would invite you to submit your sessions as well.

Remember that all speakers will be required to present at least two sessions.  So make sure you submit plenty of session abstracts to improve your odds of getting selected.

More...

We-Want-You As I indicated last week, I am pleased to announce the Call for Speakers for the 2010 DotNetNuke Connections conference.  Once again, this years conference will be held at the Mandalay Bay in Las Vegas from November 1st through the 4th with pre and post-conference training available as well. 

We could not do this show without our speakers and we have been fortunate in the past to have had some great session proposals by many well respected speakers.  Some of those speakers have been selected to present their sessions and unfortunately some of them have not been.  Such is the nature of any conference.  As usual we will continue to look for new speakers to bring fresh new topics to the conference.  So if you have submitted sessions in the past then I would encourage you to submit again.  If you have public speaking experience and some great ideas for sessions then I would invite you to submit your sessions as well.

Remember that all speakers will be required to present at least two sessions.  So make sure you submit plenty of session abstracts to improve your odds of getting selected.

More...

This article is cross-posted from my personal blog.

One of the tenets of Unit Testing is that in order to test a piece of code we often need to create some alternate implementation of one or more of the Interfaces involved in a test.  This concept is generally called a Test Double.  However there are many types of Test Double, and there is some degree of confusion about the types of doubles used.

In this installment of “Adventures in Testing” I will attempt to clarify the types of Test Doubles.

Dummies

Dummies are the simplest type of test double – these are objects that are needed to be passed around but they don’t actually do anything so they can have a very simple implementation.  Usually they are required just to fill a parameter list in a method call.

An example would be a test for the following constructor -

Figure 1: A method that can be tested using a Dummy Test Double

   1:  Public Sub New(ByVal createView As ICreateVocabularyView, _
   2:                 ByVal vocabularyController As IVocabularyController, _
   3:                 ByVal scopeTypeController As IScopeTypeController)
   4:      MyBase.New(createView)
   5:      Arg.NotNull("vocabularyController", vocabularyController)
   6:      Arg.NotNull("scopeTypeController", scopeTypeController)
   7:   
   8:      '.....
   9:  End Sub

In this example the constructor takes three parameters.  If we are testing that the constructor throws an Exception if one of the arguments are null, we need to ensure that the other parameters are not null.  So for example our test to ensure that the Constructor throws an Exception if the VocabularyController is null might look like this.

Figure 2: A test using a Dummy Test Double

   1:  public void Constructor_Requires_Non_Null_VocabularyController()
   2:  {
   3:      //Arrange
   4:      DummyCreateVocabularyView view = new DummyCreateVocabularyView();
   5:      DummyScopeTypeController scopeTypeController = new DummyScopeTypeController();
   6:   
   7:      //Act
   8:      CreateVocabularyPresenter presenter = new CreateVocabularyPresenter(view, 
   9:                                                      null, 
  10:                                                      scopeTypeController);
  11:      
  12:      //.....
  13:  }

We don’t care about the implementation of the first (ICreateVocabularyView) or third (IScopeTypeController) interfaces in this test, we just need them to be non-null – all we care about is that the constructor throws if the second parameter is null.

Fakes

The other three types of Test Doubles all have some form of implementation as we are testing some part of the Interface in question.

Fake objects usually have full working implementations, but they use some shortcut, and are not of production quality.  An example of a Fake object would be when testing the business layer of an application, where we create an in-memory Fake DataService class to simulate the data access, and allow us to test the business layer methods, without requiring a database to be set up.

Stubs

Stubs provide canned answers to calls made during a test, and usually don’t respond at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.

Mocks

Mocks are usually dynamically created by a mocking framework – (in DotNetNuke we use Moq as the mocking framework). Mock objects are preprogrammed with expectations which form a specification of the calls they are expected to receive (see Figure 3)

Figure 3; An example of using a Mock Object

   1:          public void VocabularyListPresenter_On_Add_Redirects_To_CreateVocabulary()
   2:          {
   3:              // Arrange
   4:              Mock mockController = new Mock();
   5:              Mock view = new Mock();
   6:              view.Setup(v => v.Model).Returns(new VocabularyListModel());
   7:   
   8:              Mock httpContext = new Mock();
   9:              Mock httpResponse = new Mock();
  10:              httpContext.Setup(h => h.Response).Returns(httpResponse.Object);
  11:   
  12:              VocabularyListPresenter presenter = new VocabularyListPresenter(view.Object, mockController.Object)
  13:              {
  14:                  HttpContext = httpContext.Object,
  15:                  ModuleId = Constants.MODULE_ValidId,
  16:                  TabId = Constants.TAB_ValidId
  17:              };
  18:   
  19:              // Act (Raise the AddVocabulary Event)
  20:              view.Raise(v => v.AddVocabulary += null, EventArgs.Empty);
  21:   
  22:              // Assert
  23:              httpResponse.Verify(r => r.Redirect(Globals.NavigateURL(Constants.TAB_ValidId,
  24:                                                  "CreateVocabulary",
  25:                                                  String.Format("mid={0}", Constants.MODULE_ValidId))));
  26:          }

In Figure 3 we are using 4 separate Mock objects, but lets focus on the two mocks created in lines 8 and 9.  In line 8 we create a Mock HttpContextBase using Moq’s Mock class, and in line 9 we create a Mock HttpResponseBase.  Just creating the Mock does nothing more that create in memory an object that can respond to an interface, or (as in this case) an abstract base class.

In line 10 we setup the Mock HttpContextBase, so that when it receives a call to its Response property it will return the object represented by the Mock HttpResponse object.

In line 15 we set HttpContext property of the presenter to this Mock HttpContextBase.

Now we have set up our test so we can test the view’s AdddVocabulary method (see Figure 4), which is designed to redirect to a new page when the AddVocabulary button is clicked.

Figure 4: The AddVocabulary method that Figure 3 is testing

   1:  Public Sub AddVocabulary(ByVal sender As Object, ByVal e As EventArgs)
   2:      Response.Redirect(NavigateURL(TabId, _
   3:                                    "CreateVocabulary", _
   4:                                    String.Format("mid={0}", ModuleId)))
   5:  End Sub

So, in line 21 we raise the AddVocabulary event by calling the Raise method of the Mock view.  This will cause the presenter’s event handler to be triggered and in line 24 we verify that this caused our Mock Response object to have its Redirect method called, with the expected url.

Note: This example is based on the new Model-View-Presenter code which will be included in DotNetNuke 5.3 and provides a new Module Development Framework that provides full testability.

One of the advantages of a Mocking Framework like Moq is that it can be used to replace most types of Test Double.  For example we can write the test using Dummy objects in Figure 2 to use Mocks (Figure 5).

Figure 5: The example in Figure 2 rewritten using Moq instead of Dummies

   1:  public void Constructor_Requires_Non_Null_VocabularyController()
   2:  {
   3:      //Arrange
   4:      Mock view = new Mock();
   5:      Mock scopeTypeController = new Mock();
   6:   
   7:      //Act, Assert
   8:      CreateVocabularyPresenter presenter = new CreateVocabularyPresenter(view.Object, 
   9:                                                          v, 
  10:                                                          scopeTypeController.Object);
  11:   
  12:      //..
  13:  }

This article is cross-posted from my personal blog.

One of the tenets of Unit Testing is that in order to test a piece of code we often need to create some alternate implementation of one or more of the Interfaces involved in a test.  This concept is generally called a Test Double.  However there are many types of Test Double, and there is some degree of confusion about the types of doubles used.

In this installment of “Adventures in Testing” I will attempt to clarify the types of Test Doubles.

Dummies

Dummies are the simplest type of test double – these are objects that are needed to be passed around but they don’t actually do anything so they can have a very simple implementation.  Usually they are required just to fill a parameter list in a method call.

An example would be a test for the following constructor -

Figure 1: A method that can be tested using a Dummy Test Double

   1:  Public Sub New(ByVal createView As ICreateVocabularyView, _
   2:                 ByVal vocabularyController As IVocabularyController, _
   3:                 ByVal scopeTypeController As IScopeTypeController)
   4:      MyBase.New(createView)
   5:      Arg.NotNull("vocabularyController", vocabularyController)
   6:      Arg.NotNull("scopeTypeController", scopeTypeController)
   7:   
   8:      '.....
   9:  End Sub

In this example the constructor takes three parameters.  If we are testing that the constructor throws an Exception if one of the arguments are null, we need to ensure that the other parameters are not null.  So for example our test to ensure that the Constructor throws an Exception if the VocabularyController is null might look like this.

Figure 2: A test using a Dummy Test Double

   1:  public void Constructor_Requires_Non_Null_VocabularyController()
   2:  {
   3:      //Arrange
   4:      DummyCreateVocabularyView view = new DummyCreateVocabularyView();
   5:      DummyScopeTypeController scopeTypeController = new DummyScopeTypeController();
   6:   
   7:      //Act
   8:      CreateVocabularyPresenter presenter = new CreateVocabularyPresenter(view, 
   9:                                                      null, 
  10:                                                      scopeTypeController);
  11:      
  12:      //.....
  13:  }

We don’t care about the implementation of the first (ICreateVocabularyView) or third (IScopeTypeController) interfaces in this test, we just need them to be non-null – all we care about is that the constructor throws if the second parameter is null.

Fakes

The other three types of Test Doubles all have some form of implementation as we are testing some part of the Interface in question.

Fake objects usually have full working implementations, but they use some shortcut, and are not of production quality.  An example of a Fake object would be when testing the business layer of an application, where we create an in-memory Fake DataService class to simulate the data access, and allow us to test the business layer methods, without requiring a database to be set up.

Stubs

Stubs provide canned answers to calls made during a test, and usually don’t respond at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.

Mocks

Mocks are usually dynamically created by a mocking framework – (in DotNetNuke we use Moq as the mocking framework). Mock objects are preprogrammed with expectations which form a specification of the calls they are expected to receive (see Figure 3)

Figure 3; An example of using a Mock Object

   1:          public void VocabularyListPresenter_On_Add_Redirects_To_CreateVocabulary()
   2:          {
   3:              // Arrange
   4:              Mock mockController = new Mock();
   5:              Mock view = new Mock();
   6:              view.Setup(v => v.Model).Returns(new VocabularyListModel());
   7:   
   8:              Mock httpContext = new Mock();
   9:              Mock httpResponse = new Mock();
  10:              httpContext.Setup(h => h.Response).Returns(httpResponse.Object);
  11:   
  12:              VocabularyListPresenter presenter = new VocabularyListPresenter(view.Object, mockController.Object)
  13:              {
  14:                  HttpContext = httpContext.Object,
  15:                  ModuleId = Constants.MODULE_ValidId,
  16:                  TabId = Constants.TAB_ValidId
  17:              };
  18:   
  19:              // Act (Raise the AddVocabulary Event)
  20:              view.Raise(v => v.AddVocabulary += null, EventArgs.Empty);
  21:   
  22:              // Assert
  23:              httpResponse.Verify(r => r.Redirect(Globals.NavigateURL(Constants.TAB_ValidId,
  24:                                                  "CreateVocabulary",
  25:                                                  String.Format("mid={0}", Constants.MODULE_ValidId))));
  26:          }

In Figure 3 we are using 4 separate Mock objects, but lets focus on the two mocks created in lines 8 and 9.  In line 8 we create a Mock HttpContextBase using Moq’s Mock class, and in line 9 we create a Mock HttpResponseBase.  Just creating the Mock does nothing more that create in memory an object that can respond to an interface, or (as in this case) an abstract base class.

In line 10 we setup the Mock HttpContextBase, so that when it receives a call to its Response property it will return the object represented by the Mock HttpResponse object.

In line 15 we set HttpContext property of the presenter to this Mock HttpContextBase.

Now we have set up our test so we can test the view’s AdddVocabulary method (see Figure 4), which is designed to redirect to a new page when the AddVocabulary button is clicked.

Figure 4: The AddVocabulary method that Figure 3 is testing

   1:  Public Sub AddVocabulary(ByVal sender As Object, ByVal e As EventArgs)
   2:      Response.Redirect(NavigateURL(TabId, _
   3:                                    "CreateVocabulary", _
   4:                                    String.Format("mid={0}", ModuleId)))
   5:  End Sub

So, in line 21 we raise the AddVocabulary event by calling the Raise method of the Mock view.  This will cause the presenter’s event handler to be triggered and in line 24 we verify that this caused our Mock Response object to have its Redirect method called, with the expected url.

Note: This example is based on the new Model-View-Presenter code which will be included in DotNetNuke 5.3 and provides a new Module Development Framework that provides full testability.

One of the advantages of a Mocking Framework like Moq is that it can be used to replace most types of Test Double.  For example we can write the test using Dummy objects in Figure 2 to use Mocks (Figure 5).

Figure 5: The example in Figure 2 rewritten using Moq instead of Dummies

   1:  public void Constructor_Requires_Non_Null_VocabularyController()
   2:  {
   3:      //Arrange
   4:      Mock view = new Mock();
   5:      Mock scopeTypeController = new Mock();
   6:   
   7:      //Act, Assert
   8:      CreateVocabularyPresenter presenter = new CreateVocabularyPresenter(view.Object, 
   9:                                                          v, 
  10:                                                          scopeTypeController.Object);
  11:   
  12:      //..
  13:  }

At the last Microsoft MVP summit, I was eating lunch with Jeff Paries who I had collaborated with on previous Silverlight projects, but had not met in person until that week. I commented that I had not used the Silverlight gauge he created about a year ago because it was too big...

More...

At the last Microsoft MVP summit, I was eating lunch with Jeff Paries who I had collaborated with on previous Silverlight projects, but had not met in person until that week. I commented that I had not used the Silverlight gauge he created about a year ago because it was too big...

More...

The last three weeks I have found myself extremely busy with the Skinning Contest. First, I built a module for the voting portion of the contest (with the help of Joe, thanks Joe!). When originally deployed, we found some problems with allowing everyone to vote so I apologize to those who initially couldn't vote (we have corrected this as of last week), so I spent a bit more time investigating that. Next I started preparing a skin object for public release (also for the skinning contest). Finally, I spent a good portion of this week re-packaging the 25 submissions for public consumption (this requires proper licensing, structure, naming, etc.)...

More...

The last three weeks I have found myself extremely busy with the Skinning Contest. First, I built a module for the voting portion of the contest (with the help of Joe, thanks Joe!). When originally deployed, we found some problems with allowing everyone to vote so I apologize to those who initially couldn't vote (we have corrected this as of last week), so I spent a bit more time investigating that. Next I started preparing a skin object for public release (also for the skinning contest). Finally, I spent a good portion of this week re-packaging the 25 submissions for public consumption (this requires proper licensing, structure, naming, etc.)...

More...
 Print   

dotnetnukelogo.jpg
FWS™ Dotnetnukes websites focus on  DotNetNuke® (DNN™) and Joomla! related matter. The purpose of these sites is to support and promote open source (.Net, PHP) Website and Content Management Systems.

fwsjoomla.jpg

Fws™ DotNetNukes | DNN Blogs RSS | DNN News Feeds | DNN Forums RSS |
© 2003-2009 Fryslan Webservices™  | Terms Of Use | Privacy Statement