This project is read-only.

Project: ModularMvc


The solution shows how to separate views/controllers/models in modules in a MVC application and unit test these layers using TDD:
- Data Layer
- MVC Presentation Layer (controllers)
- Service Layer


The organization of the solution:
modularmvc.png

Every "provider" in the solution implements an interface, this allow to simply write tests e use Inversion Of Control (IoC) to inject the concrete implementations to the classes that need.

A class used into the MVC application to register the views that are embedded resources in various assemblies:
public class DemoVirtualPathInitializer 
	: VirtualPathInitializer
{
	protected override void RegisterViewList()
	{
		RegisterView("FrontEnd/Index", "EyeOpen.FrontEnd.Mvc");
		RegisterView("FrontEnd/About", "EyeOpen.FrontEnd.Mvc");
		RegisterView("Security/Login", "EyeOpen.Security.Mvc");
		RegisterView("Security/Create", "EyeOpen.Security.Mvc");
	}

	protected override string GetFullName(string assembly)
	{
		return assembly + ".Core";
	}
}

Here the main HttpModule that replace the Global.asax:
public class DemoHttpModule : HttpModule
{
	protected override void RegisterCustomRoutes(RouteCollection routes)
	{
		routes
			.MapRoute(
				"Default",
				"{controller}/{action}/{id}",
				new { controller = "FrontEnd", action = "Index", id = UrlParameter.Optional });
	}

	protected override void Initialize()
	{
		DependencyResolver
			.SetResolver(new SecurityDependencyResolver());

		HostingEnvironment
			.RegisterVirtualPathProvider(new EmbeddedVirtualPathProvider(new DemoVirtualPathInitializer()));

		new DatabaseCreateAndPopulate()
			.Create(DependencyResolver.Current.GetService<ISecurityUnitOfWork>());
	}
}

The custom IDepencyResolver container:
public class SecurityDependencyResolver
	: DependencyResolverBase
{
	protected override T GetService<T>()
	{
		var serviceType = typeof(T);

		if (serviceType == typeof(SecurityController))
		{
			return
				(T)(object)new SecurityController(GetService<ISecurityUnitOfWork>());
		}

		if (serviceType == typeof(ISecurityUnitOfWork))
		{
			return
				(T)(object)new SecurityUnitOfWork(DbProviders.SqlCe, "DataSource = |DataDirectory|Security.sdf");
		}

		return default(T);
	}
}

Last but no least, a unit test to check that UserLoginService works well, here there are mock everywhere (using MOQ framework):
[TestClass]
public class UserLoginServiceTest
{
	private const string CorrectEmail = "b@b.com";
	private const string WrongEmail = "b@b1.com";

	private const string CorrectPassword = "password";
	private const string WrongPassword = "wrongpassword";

	[TestMethod]
	public void AuthenticateUsingWrongEmailAndWrongPasswordExpectedUserIsNotValid()
	{
		CheckUserCredentials(WrongEmail, WrongPassword, false);
	}

	[TestMethod]
	public void AuthenticateUsingCorrectEmailAndWrongPasswordExpectedUserIsNotValid()
	{
		CheckUserCredentials(CorrectEmail, WrongPassword, false);
	}

	[TestMethod]
	public void AuthenticateUsingWrongEmailAndCorrectPasswordExpectedUserIsNotValid()
	{
		CheckUserCredentials(WrongEmail, CorrectPassword, false);
	}

	[TestMethod]
	public void AuthenticateUsingCorrectEmailAndCorrectPasswordExpectedUserIsValid()
	{
		CheckUserCredentials(CorrectEmail, CorrectPassword, true);
	}

	private void CheckUserCredentials(string email, string password, bool expected)
	{
		new UserLoginService()
			.IsValidUser(email, password, CreateUow())
			.Should()
			.Be
			.EqualTo(expected);
	}

	private ISecurityUnitOfWork CreateUow()
	{
		var uowMock = new Mock<ISecurityUnitOfWork>();

		uowMock
			.SetupGet(x => x.UserRepository)
			.Returns(new RepositoryMock<User>(GetUserList().ToArray()).Object);

		return uowMock.Object;
	}

	private IEnumerable<User> GetUserList()
	{
		yield return
			new User
			{
				Id = Guid.NewGuid(),
				Email = CorrectEmail,
				Password = User.CreatePassword(CorrectPassword)
			};
	}
}

Last edited Oct 14, 2011 at 11:43 PM by teoarch, version 3

Comments

No comments yet.