New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

Creating Testable Modules - LinksRepository

This article is cross-posted from my personal blog.

In the previous article in this blog series on creating testable modules, I began to create the View Links feature of our LinksMVP module.  In this article I will add the concrete Repository class.

The LinksRepository Class

Listing 1 shows the LinksRepository class required to satisfy the ILinksRepository interface.  Note the addition of a new interface – IDataService. 

Listing 1 – The LinksRepository Class

   1:  public class LinksRepository : ILinksRepository
   2:  {
   3:      private IDataService dataService;
   5:      public LinksRepository(IDataService dataService)
   6:      {
   7:          this.dataService = dataService;
   8:      }
  10:      public List GetLinks(int moduleId)
  11:      {
  12:          return CBO.FillCollection(dataService.GetLinks(moduleId));
  13:      }
  14:  }

In the same way that we defined the Business Layer with an ILinksRepository interface, we define the Data Layer with the IDataService interface. 

I am using IDataService (and DataService as the concrete implementation) as I intend to use the DAL+ – the DAL+ is a set of core DataProvider methods that allow me as a Module Developer to avoid having to create my own DataProvider/SqlDataProvider combination – we will see how this works when we get to the Data Layer. 

I could bypass the use of a DataService layer in my module and just call the core DAL+ methods directly from the Repository class – but then I would have my Repository tightly-coupled with the DotNetNuke core Data Layer, and I would not be able to test it independently.  In this way I can test my Repository by using a MockDataService.

Testing the LinksRepository Class

Listing 2 shows the test for testing the LinksRepository class.  This test looks very similar to the test for the Presenter.

Listing 2 – Testing the LinksRepository

   1:  [TestMethod]
   2:  public void Repository_Should_Retrieve_All_Links_When_ModuleId_Is_Valid()
   3:  {
   4:      //First create a MockDataService
   5:      MockDataService dataService = new MockDataService();
   7:      //Next create a LinksRepository
   8:      LinksRepository repository = new LinksRepository(dataService);
  10:      //Get the Links from the Repository
  11:      List links = repository.GetLinks(MockHelper.ValidModuleId);
  13:      Assert.AreEqual<int>(2, links.Count);
  14:  }

In line 5 we create a MockDataService (Listing 3), which returns a DataReader which we generate in the MockHelper.CreateLinksReader method (Listing 4).  In line 8 we create our LinksRepository and pass it our MockDataService instance.  We then call the GetLinks method in line 11 and assert that we did get the correct number of links returned.

Listing 3 – The MockDataService class

   1:  public class MockDataService : IDataService
   2:  {
   3:      public IDataReader GetLinks(int moduleId)
   4:      {
   5:          //Get the Mock Links Reader
   6:          return MockHelper.CreateLinksReader(moduleId);
   7:      }
   8:  }

Listing 4 – The CreateLinksReader method in MockHelper

   1:  public static IDataReader CreateLinksReader(int moduleId)
   2:  {
   3:      DataTable datatable = new DataTable();
   4:      datatable.Columns.Add("ModuleId");
   5:      datatable.Columns.Add("LinkId");
   6:      datatable.Columns.Add("LinkURL");
   7:      datatable.Columns.Add("Title");
   8:      datatable.Columns.Add("ViewOrder");
  10:      for (int i = 1; i < 3; i++)
  11:          datatable.Rows.Add(moduleId, i, String.Format(LinkURL, i), String.Format(Title, i), i);
  13:      return datatable.CreateDataReader();
  14:  }

So this test is fairly straightforward – we should get a green light (see Figure 1).

Figure 1 – Test Results with our new Links Repository Tests

But wait, we get a red light – our test fails.  If we double-click on the failing test result we can find out why the test fails (See Figure 2).

Figure 2 – Failing Test Result Detail

So, what is the problem.  Our LinksRepository calls the core CBO method FillCollection method.  This method uses reflection to match the DataReader column names to the correct properties, but because of the expense of reflection calls, the CBO class uses caching, and the test fails because there is no CachingProvider to instantiate.

IoC Container to the Rescue

Prior to 5.0, this behaviour was a deal-breaker.  All the providers are loaded by the core based on the web.config settings, so prior to 5.0 we would have to launch the web-browser in order to get a web context, to load our providers.

However, recognizing that this causes unnecessary coupling, in 5.0 we modified this behaviour by introducing a simple IoC (Inversion of Control) container, and in the Application_Start method of global.asax.vb all the providers are loaded to make them available. 

If you look at the first and second lines of the stack trace in Figure 2 our error is happening because there is no Container and therefore no CachingProvider available.

But, in 5.0, it is simple enough to create an instance of the Container in our test method and add a CachingProvider instance to it (see Listing 5), so we can test the LinksRepository without worrying about a web context.

Listing 5 – The Revised LinskRepository Test

   1:  [TestMethod]
   2:  public void Repository_Should_Retrieve_All_Links_When_ModuleId_Is_Valid()
   3:  {
   4:      //Create a Container
   5:      ComponentFactory.Container = new SimpleContainer();
   7:      //Create a File Based Cache Provider and register it in the Container as the CBO class
   8:      //in the DotNetNuke Framework requires a Caching Provider
   9:      ComponentFactory.RegisterComponentInstance(new FBCachingProvider());
  11:      //Now create a MockDataService
  12:      MockDataService dataService = new MockDataService();
  14:      //Next create a LinksRepository
  15:      LinksRepository repository = new LinksRepository(dataService);
  17:      //Get the Links from the Repository
  18:      List links = repository.GetLinks(MockHelper.ValidModuleId);
  20:      Assert.AreEqual<int>(2, links.Count);
  21:  }

When we do this we get three out of three green lights.

One more layer to go (the Data Layer) and then we can go back and build our actual LinksView UserControl.  In the next article in this series I will build the DataService class and create a test for it.


Comment Form

Only registered users may post comments.


Aderson Oliveira (22)
Alec Whittington (11)
Alessandra Davies (3)
Alex Shirley (10)
Andrew Hoefling (3)
Andrew Nurse (30)
Andy Tryba (1)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (37)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Bogdan Litescu (1)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (213)
Chris Paterra (55)
Clint Patterson (108)
Cuong Dang (21)
Daniel Bartholomew (2)
Daniel Mettler (181)
Daniel Valadas (48)
Dave Buckner (2)
David Poindexter (12)
David Rodriguez (3)
Dennis Shiao (1)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (80)
Francisco Perez Andres (17)
Geoff Barlow (12)
George Alatrash (12)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (274)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Kelly Ford (4)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matt Rutledge (2)
Matthias Schlomann (16)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Miguel Gatmaytan (3)
Mike Horton (19)
Mitchel Sellers (40)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Oliver Hine (1)
Patricio F. Salinas (1)
Patrick Ryan (1)
Peter Donker (54)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Sacha Trauwaen (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott Schlesier (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Steven Fisher (1)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (3)
Tycho de Waard (4)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (40)
Will Strohl (180)
William Severance (5)
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out