I created a unit test to a log in a user, using an api controller and the membership is checking the user that is in my Dto using this line of code.
MembershipUser membershipUser = System.Web.Security.Membership.GetUser(Username);
On the web application this is working well, but on the test project and my unit test I am having this exception.
Access to the path 'C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 12.0\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\TESTWINDOW\App_Data' is denied.
How should register my System.Web.Security.Membership to avoid this issue in the unit test?
My test method looks like this:
[TestMethod]
public void LoginSuccessfullyAnUser()
{
//Arrange
var controller = new TokensController(unitOfWork, unitOfWorkMembership, configManager);
var credentials = new LoginUserDTO
{
Username = "user1",
Password = "12345678"
};
controller.Request = new HttpRequestMessage
{
RequestUri = new Uri("http://localhost/api/tokens")
};
controller.Configuration = new HttpConfiguration();
controller.Configuration.Routes.MapHttpRoute(name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
controller.RequestContext.RouteData = new HttpRouteData(route: new HttpRoute(),
values: new HttpRouteValueDictionary
{
{ "controller", "tokens" }
});
//Act
var response = controller.Post(credentials);
//Assert
Assert.IsNotNull(response);
}
You will have to wrap Membership around a class e.g. MembershipService. All the membership API you are invoking will be redirected through this class. This basically give you the ability to mock the actual Membership class behavior in Unit Test.
So let's see some code:
Controller.cs
[HttpPost]
public JsonResult GetLoggedInUserName()
{
MembershipUser mem = _membershipService.GetUserDetails(User.Identity.Name);
Guid membershipId = new Guid(mem.ProviderUserKey.ToString());
var organizationUser = _organizationUserService.GetUserDetailsByMembershipId(membershipId);
var name = organizationUser.FirstName + " " + organizationUser.LastName;
return Json(name);
}
MembershipService.cs
public class MembershipService : IMembershipService
{
public MembershipUser GetUserDetails(string emailAddress)
{
return Membership.GetUser(emailAddress);
}
}
MyTests.cs
[TestMethod()]
public void GetLoggedInUserName_InvokedWithValidSetup_ReturnUserName()
{
// Arrange
// Setup membership to return mocked user
var membershipService = new Mock<IMembershipService>();
var user = new Mock<MembershipUser>();
user.Setup(x => x.UserName).Returns("Adam");
user.Setup(x => x.ProviderUserKey).Returns("1df03f8c-74fa-423a-8be8-61350b4da59f");
user.SetupGet(x => x.Email).Returns("adamw@test.com");
membershipService.Setup(m => m.GetUserDetails(It.IsAny<string>())).Returns(user.Object);
// Setup organization user service - You can ignore it or replace
// based on what you are using.
var organizationUserService = new Mock<IOrganizationUserService>();
var organizationUser = new OrganizationUser
{
FirstName = "Adam",
LastName = "Woodcock",
MembershipId = new Guid("1df03f8c-74fa-423a-8be8-61350b4da59f")
};
organizationUserService.Setup(s => s.GetUserDetailsByMembershipId(It.IsAny<Guid>())).Returns(organizationUser);
var mock = new Mock<ControllerContext>();
mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("Adam");
var target = GetTargetController(membershipService, null, organizationUserService, null, null);
target.ControllerContext = mock.Object;
// Act
var result = target.GetLoggedInUserName();
// Assert
Assert.AreEqual(organizationUser.FirstName + " " + organizationUser.LastName, result.Data);
}
Hope this helps.