Unit Testing allows the developer to create solid applications that will last the changes in the future. There are several articles on GridViewGuy that covers the concepts and benefits of Unit Testing. In this article we are going to go one step further and create Unit Tests for our Membership and Role providers.
Introduction:
Unit Testing allows the developer to create solid applications that will last the changes in the future. There are several articles on GridViewGuy that covers the concepts and benefits of Unit Testing. In this article we are going to go one step further and create Unit Tests for our Membership and Role providers.
Why Test Membership and Role Providers?
If you are building an ASP.NET 2.0 application with multi user support then it is quite possible that you will be using the Membership and Role provider model for authentication. Authentication and authorization are one of the most important aspects of any web application that must be tested thoroughly. Unit Tests will indicate that if the providers are working as expected or will they need some work.
Creating Membership Provider:
You can either use the built-in Membership provider or create your own from scratch. We will be inheriting our provider from the SqlMembershipProvider. Take a look at the code below:
public class VirtualRoomProvider : SqlMembershipProvider
{
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
MembershipUser user = base.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
// assign the default role as a student
VirtualRoomRoleProvider roleProvider = new VirtualRoomRoleProvider();
roleProvider.AddUsersToRoles(new string[] { username }, new string[] { "Student" });
return user;
}
}
Nothing fancy here! The provider uses the default CreateUser method to create the new user and then it assigns the student role to the newly created user.
Testing Membership Provider:
Let’s create Unit Tests for the provider created above. We will be using MbUnit but you are free to use any Unit Testing Framework.
Before we start writing our tests let’s create a Base class for our tests.
[TestFixture]
public class BaseTest
{
protected string _username;
protected string _password;
protected string _email;
protected VirtualRoomProvider _provider;
protected NameValueCollection _config;
protected MembershipCreateStatus _status = new MembershipCreateStatus();
[SetUp]
public void initialize()
{
_username = "mary";
_password = "marykate$";
_email = "marykate@gmail.com";
// setup the membership provider
_provider = new VirtualRoomProvider();
_config = new NameValueCollection();
_config.Add("applicationName", "VirtualRoom");
_config.Add("name", "VirtualRoomProvider");
_config.Add("requiresQuestionAndAnswer", "false");
_config.Add("connectionStringName", "VirtualRoomConnectionString");
_provider.Initialize(_config["name"], _config);
_status = new MembershipCreateStatus();
}
}
The purpose of the BaseTest class is to provide with the variables and data to the child classes. The BaseTest class initialize method is marked with the Setup attribute which indicates that it will be fired before running every test. Those tests can also reside in the child classes.
Let’s take a look at a simple test.
[TestFixture]
public class when_a_new_user_creates_an_account : BaseTest
{
[Test]
[RollBack]
public void should_create_an_account_successfully()
{
_provider.CreateUser(_username, _password, _email, null, null, true, null, out _status);
Assert.AreEqual(MembershipCreateStatus.Success, _status);
}
}
The test checks that when the user creates an account it is created successfully. If you run the test you will get some error “Object reference not set to an instance of an object”. This is because there is no configuration for the Membership provider. Add an App.config file in the testing project and add the following configuration.
<connectionStrings>
<add name="VirtualRoomConnectionString" connectionString="Server=localhost;Database=VirtualRoomsDB;Trusted_Connection=true"/>
</connectionStrings>
<system.web>
<roleManager enabled="true" defaultProvider="VirtualRoomRoleProvider" cacheRolesInCookie="true"
cookieName="VirtualRoomCookie">
<providers>
<add name="VirtualRoomRoleProvider" type="System.Web.Security.SqlRoleProvider"
connectionStringName="VirtualRoomConnectionString" applicationName="VirtualRoom"/>
</providers>
</roleManager>
<membership defaultProvider="VirtualRoomProvider">
<providers>
<remove name="AspNetSqlMembershipProvider"/>
<add applicationName="VirtualRoom" requiresQuestionAndAnswer="false"
requiresUniqueEmail="true" minRequiredNonalphanumericCharacters="0"
enablePasswordReset="true" passwordFormat="Hashed" connectionStringName="VirtualRoomConnectionString"
name="VirtualRoomProvider" type="DomainObjects.Providers.VirtualRoomProvider,DomainObjects" />
</providers>
</membership>
</system.web>
Now, if you run the test it will pass.
Unit Testing Membership Role Provider:
Let’s first see the implementation of the role provider.
public class VirtualRoomRoleProvider : SqlRoleProvider
{
private NameValueCollection _roleConfig = new NameValueCollection();
public VirtualRoomRoleProvider()
{
_roleConfig.Add("applicationName", "VirtualRoom");
_roleConfig.Add("connectionStringName", "VirtualRoomConnectionString");
this.Initialize("VirtualRoomRoleProvider", _roleConfig);
}
}
Make sure you have the configuration settings in the App.config file before initializing the RoleProvider.
Now, let’s take a look at the Unit Tests:
[TestFixture]
public class when_a_user_is_assigned_a_role : BaseTest
{
[Test]
public void should_be_able_to_initialize_role_provider()
{
VirtualRoomRoleProvider roleProvider = new VirtualRoomRoleProvider();
Assert.AreEqual("VirtualRoom", roleProvider.ApplicationName);
Assert.AreEqual("VirtualRoomRoleProvider", roleProvider.Name);
}
[Test]
public void should_verify_that_the_roles_exists()
{
Assert.IsTrue(_roleProvider.GetAllRoles().Count() > 0,"No roles exists");
}
[Test]
[RollBack]
public void should_assign_the_student_role_to_the_new_user()
{
MembershipUser user = _provider.CreateUser(_username, _password, _email, null, null, true, null, out _status);
Assert.IsTrue(_roleProvider.IsUserInRole(user.UserName, "Student"),"User is not a student!");
}
[Test]
[RollBack]
public void should_be_able_to_add_the_user_to_the_tutor_role()
{
MembershipUser user = _provider.CreateUser(_username, _password, _email, null, null, true, null, out _status);
_roleProvider.AddUsersToRoles(new string[] { user.UserName }, new string[] { "Tutor" });
Assert.IsTrue(_roleProvider.IsUserInRole(user.UserName, "Tutor"), "User does not belong to the correct role");
}}
Above you can see some of the tests associated with the Role provider. The Unit Tests ensures that the Role provider is working properly.
Conclusion:
Unit testing the application allows the developer to remove bugs early and make good design decisions. Multi user application depends heavily on the Membership and Role provider and hence it is very important to unit test the authentication and authorization module.
I hope you liked this article! Happy coding!