Programming through interfaces

Here’s a quick example of how we do layer seperation through interfaces to make each layer testable. Although the tests run, the UI section is untested. Download file.

[csharp]
using System;
using System.Web;
using System.Web.UI;
using NMock;
using NUnit.Framework;
using Socialanimal.Example.Business;
using Socialanimal.Example.Business.Implementation;
using Socialanimal.Example.Core.Entities;
using Socialanimal.Example.Core.Interfaces;
using Socialanimal.Example.SqlDatabase;

namespace Socialanimal.Example.Core.Entities
{
public class Employee
{
public string Forename;
public string Surname;

public Employee(string forename, string surname)
{
this.Forename = forename;
this.Surname = surname;
}
}
}

namespace Socialanimal.Example.Core.Interfaces
{
public interface IFacade
{
Employee GetEmployee(string surname);
}

public interface IBusinessManager
{
Employee GetEmployee(string surname);
}

public interface IDatabaseProvider
{
Employee GetEmployee(string forename, string surname);
}
}

namespace Socialanimal.Example.Business
{
public class FacadeFactory
{
public IFacade CreateFacade()
{
IDatabaseProvider databaseProvider = new SqlDatabaseProvider(“server=localhost;database=test”);
IBusinessManager businessManager = new BusinessManager(databaseProvider);
IFacade facade = new Facade(businessManager);
return facade;
}
}

public class Facade : IFacade
{
private IBusinessManager businessManager;

public Facade(IBusinessManager businessManager)
{
this.businessManager = businessManager;
}

#region IFacade Members

public Employee GetEmployee(string surname)
{
return businessManager.GetEmployee(surname);
}

#endregion
}
}

namespace Socialanimal.Example.Business.Implementation
{
public class BusinessManager : IBusinessManager
{
private IDatabaseProvider databaseProvider;

public BusinessManager(IDatabaseProvider databaseProvider)
{
this.databaseProvider = databaseProvider;
}

#region IBusinessManager Members

public Employee GetEmployee(string surname)
{
if (surname == null)
{
throw new ArgumentNullException(“surname”);
}
return databaseProvider.GetEmployee(null, surname);
}

#endregion
}
}

namespace Socialanimal.Example.SqlDatabase
{
public class SqlDatabaseProvider : IDatabaseProvider
{
public SqlDatabaseProvider(string connectionString)
{
}

#region IDatabaseProvider Members

public Employee GetEmployee(string forename, string surname)
{
// Get from database
return new Employee(“john”, “doe”);
}

#endregion
}
}

namespace Socialanimal.Example.ClientWebSite
{
public class BasePage : Page
{
private IFacade Facade
{
get { return HttpContext.Current.Items[“Facade”] as IFacade; }
}

protected override void OnLoad(EventArgs e)
{
Employee employee = this.Facade.GetEmployee(“john”);
Response.Write(employee.Forename + employee.Surname);
base.OnLoad(e);
}
}

// global_asax
public class Global : HttpApplication
{
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpContext.Current.Items[“Facade”] = new FacadeFactory().CreateFacade();
}
}
}

namespace Socialanimal.Example.Business.Tests
{
[TestFixture]
public class FacadeTest
{
[Test]
public void TestFacade()
{
// Create a mock IBusinessManager
DynamicMock mock = new DynamicMock(typeof (IBusinessManager)); // Create a proper Facade
Facade f = new Facade((IBusinessManager) mock.MockInstance); // Set expectations for this request
Employee expectedResult = new Employee(“john”, “smith”);
mock.ExpectAndReturn(“GetEmployee”, expectedResult, null, “smith”);
Employee actualResult = f.GetEmployee(“smith”);
Assert.AreEqual(expectedResult.Forename, actualResult.Forename);
Assert.AreEqual(expectedResult.Surname, actualResult.Surname);
mock.Verify();
}
}

[TestFixture]
public class BusinessManagerTest
{
[Test]
public void TestBusinessManager()
{
// Create a mock IDatabaseProvider
DynamicMock mock = new DynamicMock(typeof (IDatabaseProvider));
// Create a proper BusinessManager
BusinessManager bm = new BusinessManager((IDatabaseProvider) mock.MockInstance);
// Set expectations for this request
Employee expectedResult = new Employee(“john”, “smith”);
mock.ExpectAndReturn(“GetEmployee”, expectedResult, null, null, “smith”);
Employee actualResult = bm.GetEmployee(“smith”);
Assert.AreEqual(expectedResult.Forename, actualResult.Forename);
Assert.AreEqual(expectedResult.Surname, actualResult.Surname);
mock.Verify();
}

[Test]
public void TestGetEmployeeWithNullSurname()
{
// Create a mock IDatabaseProvider
DynamicMock mock = new DynamicMock(typeof (IDatabaseProvider));
try
{
// Create a proper BusinessManager
BusinessManager bm = new BusinessManager((IDatabaseProvider) mock.MockInstance);
bm.GetEmployee(null);
}
catch (ArgumentNullException ex)
{
Assert.AreEqual(“surname”, ex.ParamName);
}
finally
{
mock.Verify();
}
}
}
}
[/csharp]

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s