I am trying to perform a unit test of an n-tier application, service layer, repository layer and web api controllers. My repositories are checking the Thread.CurrentPrincipal object to get the current user. This is where I have a problem, when I create the implementation class that inherits from IPrincipal it does allow me to set the IsUserAuthenticated. Is there a way to simulate this for my unit tests. I would like to set the Thread.CurrentPrincipal to my implementation object. How would I simulate a user in this way?
In my RepositoryBase code, I call the following to determine if user is authenticated:
public bool IsUserAuthenticated
{
get { return ((UserPrincipal)Principal).Identity.IsAuthenticated; }
}
The actual test looks something like:
Contract.Requires<UserAccessException>(IsUserAuthenticated, "Illegal Access.");
I am pulling IsUserAuthenticated from the UserPrincipal below:
namespace HeyLetsTrain.Toolkit.Helper.Authentication
{
public class UserPrincipal : IPrincipal
{
IIdentity _identity;
string[] _role;
string _emailAddress;
public UserPrincipal(string name, string[] role)
{
if (role != null)
{
_role = new string[role.Length];
_role.CopyTo(role, 0);
Array.Sort(_role);
}
_identity = new GenericIdentity(name);
}
public IIdentity Identity
{
get { return _identity; }
}
public string EmailAddress
{
get { return _emailAddress; }
set { this._emailAddress = value; }
}
public bool IsInRole(string role)
{
return Array.BinarySearch(_role, role) >= 0 ? true : false;
}
public bool IsInAllRoles( params string [] roles )
{
foreach (string searchrole in roles )
{
if (Array.BinarySearch(_role, searchrole) < 0 )
return false;
}
return true;
}
public bool IsInAnyRoles( params string [] roles )
{
foreach (string searchrole in roles )
{
if (Array.BinarySearch(_role, searchrole ) > 0 )
return true;
}
return false;
}
}
}
I would wrap Thread.CurrentPrincipal call with a class and then extract the interface. This approach would allow me to pass my dummy implementation as a dependency.
Another approach is to prepare static class like this:
Then you have to use ApplicationPrincipal.Current in your repositories instead of direct call. In your tests you will be able to switch default logic by calling ApplicationPrincipal.SwitchCurrentPrincipal(() => myPrincipal).
Edit:
I would change:
With:
And then in arrange section of the test I would change default IPrincipal with:
I assume you can somehow overload the value of IsAuthenticated in UserPrincipal object.