ASP.NET-MVC – Moq Roles.Addusertorole Test

I am using Moq and the MvcContrib TestHelper class to write unit tests for projects in ASP.NET MVC 1.0. I encountered a problem.

When I When I come to Roles.AddUserToRole in my AccountController, I get a System.NotSupportedException. The Roles class is static, and Moq cannot simulate a static class.

What can I do?

You can use patterns like DI (Dependency Injection). In your case, I The RoleProvider will be passed to the AccountController. By default, it will be the default RoleProvider and the mock object in the test. It’s like:

public class AccountController< br />{
private MembershipProvider _provider;
private RoleProvider roleProvider;

public AccountController()
: this(null, null)
{
}

public AccountController(MembershipProvider provider, RoleProvider roleProvider)
{
_provider = provider ?? Membership.Provider;
this.roleProvider = roleProvider ?? System .Web.Security.Roles.Provider;
}
}

MVC runtime will call the default constructor, and the constructor will use the default role provider to initialize the AccountController. In the unit During the test, you can directly call the overloaded constructor and pass the MockRoleProvider (or use Moq to create it for you):

[Test]
public void AccountControllerTest( )
{
AccountController controller = new AccountController(new MockMembershipProvider(), new MockRoleProvider());
}< /pre>

Edit: This is how I simulate the entire HttpContext, including the main user.
To get the Moq version of HttpContext:

public static HttpContextBase GetHttpContext(IPrincipal principal)
{
var httpContext = new Mock();
var request = new Mock();
var response = new Mock( );
var session = new Mock();
var server = new Mock();
var user = principal;

< br /> httpContext.Setup(ctx => ctx.Request).Returns(request.Object);
httpContext.Setup(ctx => ctx.Response).Returns(response.Object);
httpContext .Setup(ctx => ctx.Session).Returns(session.Object);
httpContext.Setup(ctx => ctx.Server).Returns(server.Object);
httpContext.Setup(ctx => ctx.User).Returns(user);

return httpContext.Object;
}

The simulation implementation of Principal:

< /p>

public class MockPrincipal: IPrincipal
{
private IIdentity _identity;
private readonly string[] _roles;

public MockPrincipal(IIdentity identity, string[] roles)
{
_identity = identity;
_roles = roles;
}

public IIdentity Identity
{
get {return _identity; }
set {this._identity = value; }
}
< br /> public bool IsInRole(string role)
{
if (_roles == null)
return false;
return _roles.Contains(role);
}
}

MockIdentity:

public class MockIdentity: IIdentity
{
private readonly string _name;

public MockIdentity(string userName) {
_name = userName;
}

public override string AuthenticationType
{
get {throw new System.NotImplementedException(); }
}

public override bool IsAuthenticated
{
get {return !String.IsNullOrEmpty(_name); }
}

public override string Name
{
get {return _name; }
}
}

The magical call:

MockIdentity identity = new MockIdentity("JohnDoe");
var httpContext = MoqHelpers.GetHttpContext(new MockPrincipal(identity, null));

Please note that I edited the code above to omit some customizations, but I am pretty sure this should still work.

I am using Moq and MvcContrib TestHelper class Writing unit tests for the project in ASP.NET MVC 1.0. I encountered a problem.

When I came to Roles.AddUserToRole in my AccountController, I got a System.NotSupportedException. The Roles class is static, and Moq cannot simulate a static class.

What can I do?

You can use a pattern like DI (Dependency Injection). In your case, I will pass RoleProvider to AccountController, by default it will It is the default RoleProvider and is the mock object in the test. It is like:

public class AccountController
{
private MembershipProvider _provider;
private RoleProvider roleProvider;

public AccountController()
: this(null, null)
{
}

public AccountController(MembershipProvider provider, RoleProvider roleProvider)
{
_provider = provider ?? Membership.Provider;
this.roleProvider = roleProvider ?? System.Web.Security.Roles.Provider;
}
}

MVC runtime will call the default constructor, and the constructor will use the default role provider to initialize AccountController. In the unit test, you can directly call the overloaded constructor , And pass MockRoleProvider (or use Moq to create it for you):

[Test]
public void AccountControllerTest()
{
AccountController controller = new AccountController(new MockMembershipProvider(), new MockRoleProvider());
}

Edit: This is how I simulate the entire HttpContext, including the main user.
To get HttpConte The Moq version of xt:

public static HttpContextBase GetHttpContext(IPrincipal principal)
{
var httpContext = new Mock();
var request = new Mock();
var response = new Mock();
var session = new Mock();
var server = new Mock();
var user = principal;


httpContext.Setup(ctx => ctx.Request).Returns(request.Object);
httpContext.Setup(ctx => ctx.Response).Returns(response.Object);
httpContext.Setup(ctx => ctx.Session).Returns(session.Object);
httpContext.Setup (ctx => ctx.Server).Returns(server.Object);
httpContext.Setup(ctx => ctx.User).Returns(user);

return httpContext.Object;
}

Mock implementation of Principal:

public class MockPrincipal: IPrincipal
{
private IIdentity _identity;< br /> private readonly string[] _roles;

public MockPrincipal( IIdentity identity, string[] roles)
{
_identity = identity;
_roles = roles;
}

public IIdentity Identity
{
get {return _identity; }
set {this._identity = value; }
}

public bool IsInRole(string role)
{
if (_roles == null)
return false;
return _roles.Contains(role);
}
}

MockIdentity:

public class MockIdentity: IIdentity
{
private readonly string _name;

public MockIdentity(string userName) {
_name = userName;
}

public override string AuthenticationType
{
get {throw new System.NotImplementedException(); }
}
< br /> public override bool IsAuthenticated
{
get {return !String.IsNullOrEmpty(_name); }
}

public override string Name
{
get {return _name; }
}
}

The magical call:

MockIdentity identity = new MockIdentity("JohnDoe" );
var httpContext = MoqHelpers.GetHttpContext(new MockPrincipal(identity, null));

Please note that I edited the above code and omitted some custom things, but I am very Make sure this should still work.

Leave a Comment

Your email address will not be published.