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:

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