Unit Test(mvc) -problem with Roles
Asked Answered
E

3

5

I have mvc application and I'm working with poco objects and writing unit test. Problem is that all my test fail when they reach this line of code Roles.IsUserInRole("someUser", "role"). Should I implement new interface or repository for Roles or...? Thx

Ev answered 4/1, 2011 at 15:11 Comment(4)
There isn't enough info here to answer your question. Please consider revising/adding code/adding details to your question.Overtone
Why do they fail? Can you post details of the exception and which framework you are using? Most frameworks use types of exceptions to fail, so it may be a fail or an exception caused by the isolation for the test.Torbert
I have implemented Role testing in the controller similar to unit-testing-security-model-clickonceRegnal
This is error message : System.Configuration.Provider.ProviderException: The Role Manager feature has not been enabled.Ev
T
11

I had the same problem when trying to mock the Roles.IsUserInRole functionality in my coded unit tests. My solution was to create a new class called RoleProvider and an interface with method IsUserInRole which then called the System.Web.Security.Roles.IsUserInRole:

public class RoleProvider: IRoleProvider
{
    public bool IsUserInRole(IPrincipal userPrincipal)
    {
        return System.Web.Security.Roles.IsUserInRole(userPrincipal.Identity.Name, "User");
    }
}

Then in my code I call the RoleProvider IsUserInRole method. As you have an interface you can then mock the IRoleProvider in your tests, example shown here is using Rhino Mocks:

var roleProvider = MockRepository.GenerateStub<IRoleProvider>();
roleProvider.Expect(rp => rp.IsUserInRole(userPrincipal)).Return(true);

Hope this helps.

Toussaint answered 4/1, 2011 at 17:7 Comment(1)
This is very excellent for testability. Kinda annoying that my controllers now need an instance of RoleProvider, though. May end up creating a base controller class that has this built in (along with some other common properties/fields). Thanks for the suggestion!Wooden
N
0

You can set up a custom method to check roles that will behave differently in tests, but I prefer to have the tests set up a context that will work with the standard methods.

http://stephenwalther.com/blog/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-context.aspx

Needlecraft answered 5/1, 2011 at 0:35 Comment(0)
T
0

You could create a light wrapper with a Predicate/Func.

public static Predicate<string> IsUserInRole = role => Roles.IsUserInRole(role);

Then use IsUserInRole() instead of Roles.IsUserInRole(). At run time you get the same behavior. But at test time you can override the function so that it doesn't access the RoleProvider

MyClass.IsUserInRole = role => true;

If you prefer to not have a public static you could inject the Predicate via your constructor and store it as a private readonly.

class MyClass
{    
    private readonly Predicate<string> IsUserInRole;
    MyClass(Predicate<string> roleChecker) { this.IsUserInRole = roleChecker }
    MyClass() : this(role => Roles.IsUserInRole(role)) { }
}

If you use Moq you can return a mock and then control the return value and/or check the method was called. And check what parameter value was sent to the Predicate.

Mock<Predicate<string>> mockRoleChecker = new Mock<Predicate<string>>();
var cut = new MyClass(mockRoleChecker.Object);
var expectedRole = "Admin";
mockRoleChecker.SetReturnsDefault<bool>(true);  // if not specified will return false which is default(bool)

cut.MyMethod();

mockRoleChecker.Verify(x => x(expectedRole), Times.Once());
Todo answered 25/2, 2015 at 21:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.