Subscribe to
Posts
Comments

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.

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();
			}
		}
	}
}