I am starting a web application that will use asp.net membership services (with sql server backend) to keep track of users and RavenDb for everything else.
I am new to unit testing and would appreciate it if I could skip past what I still have with one example.
This is HelixManager
public class HelixManager:IDisposable { private readonly IMembershipProvider _membership; private readonly IRepository _repos; public HelixManager() { _membership = new AspNetMembershipProvider(); _repos = new RavenRepository(); } public HelixManager(IMembershipProvider membershipProvider, IRepository repos) { _membership = membershipProvider; _repos = repos; } public User CreateAdmin(User newUser, string password) { if (String.IsNullOrEmpty(newUser.Email)) throw new ArgumentException("Email must be supplied"); if (String.IsNullOrEmpty(password)) throw new ArgumentException("Password must be supplied"); var memberId = _membership.CreateUser(newUser, password); if (memberId != null) { _membership.AddToRole(newUser, "Admin"); newUser.Type = UserType.Admin; newUser.MemberId = memberId; _repos.Store<User>(newUser); } return newUser; }
This is IMembershipProvider
public interface IMembershipProvider { string CreateUser(User newUser, string password); void AddToRole(User user, string rolename); }
and implementation of AspNetMembershipProvider
public class AspNetMembershipProvider : IMembershipProvider { public string CreateUser(User newUser, string password) { MembershipCreateStatus status; MembershipUser memUser = System.Web.Security.Membership.CreateUser(newUser.Email, password, newUser.Email, "", "", true, out status); return memUser.ProviderUserKey.ToString(); } public void AddToRole(User user, string role) { Roles.AddUserToRole(user.Email, role); } }
This is IRepository
public interface IRepository { T Store<T>(T item); }
and its implementation
public class RavenRepository : IRepository { private readonly DocumentStore _store; public RavenRepository() { _store = new DocumentStore { DefaultDatabase = "Helix", Url = "http://localhost:8080" }; _store.Initialize(); } public T Store<T>(T item) { using (var session = _store.OpenSession()) { session.Store(item); session.SaveChanges(); } return item; } }
In my test project, I created fake implementations of both of them:
FakeMembershipProvider:
class FakeMembershipProvider : IMembershipProvider { public string CreateUser(User newUser, string password) { CreatedUser = true; return newUser.Email == " email@example.com " ? Guid.NewGuid().ToString() : null; } public void AddToRole(User user, string rolename) { AddedToRole = true; } public bool AddedToRole; public bool CreatedUser; }
and FakeRepository:
public class FakeRepository : IRepository { public T Store<T>(T item) { StoreCalled = true; return item; } public bool StoreCalled; }
Testing is carried out as follows:
public class UserManagementTests { private readonly HelixManager _hm; private readonly IMembershipProvider _fakeMembershipProvider; private readonly IRepository _fakeRepository; public UserManagementTests() { _fakeMembershipProvider = new FakeMembershipProvider(); _fakeRepository = new FakeRepository(); _hm = new HelixManager(_fakeMembershipProvider, _fakeRepository); } [TestMethod] public void CreateAdminReturnsValidAdminUser() { var newUser = new User { AvatarName = "fred", Email = " email@example.com ", Forename = "Fred", Surname = "Jones" }; _hm.CreateAdmin(newUser, "password"); Assert.IsNotNull(newUser.MemberId); Assert.AreEqual(UserType.Admin, newUser.Type); }
What do I ask before I get a further path along this line, is this happening correctly? Or are there any better ways to do this?
I also plan to have an IntegrationTests project that will use real db and a real RavenDb instance to test end to end.
Greetings
Dave