Unit testing custom MembershipProvider.ValidateUser, using code in Global.asax - asp.net-mvc-3

I have a unit test to check my AccountController.LogIn method. A redirect result is returned to indicate successs, otherwise a viewresult is returned.
The test always fails as the return type is always viewresult, even though the test should return success as the credentials are valid, however I can't identify where the problem is.
My TestMethod:
CustomerRepositoryTest.cs
[TestMethod]
public void Can_Login_With_Valid_Credentials()
{
// Arrange
Mock<IAddressRepository> mockAddressRepository = new Mock<IAddressRepository>();
Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
Mock<IOrderRepository> mockOrderRepository = new Mock<IOrderRepository>();
LoginViewModel model = new LoginViewModel
{
Email = "me#5.com",
Password = "password"
};
AccountController target = new AccountController(mockCustomerRepository.Object, mockAddressRepository.Object, mockOrderRepository.Object);
// Act
ActionResult result = target.LogIn(model);
// Assert
Assert.IsInstanceOfType(result, typeof(RedirectResult));
Assert.AreEqual("", ((RedirectResult)result).Url);
}
When I run the test, it fails in My AccountController Login method when I call ValidateUser
AccountController.cs
if (Membership.ValidateUser(LoginModel.Email, LoginModel.Password))
{
...
return RedirectToRoute(new
{
controller = "Account",
action = "Details"
});
}
else
{
return View();
}
My custom MembershipProvider ValidateUser looks like this:
AccountMembershipProvider.cs
public class AccountMembershipProvider : MembershipProvider
{
[Inject]
public ICustomerRepository repository { get; set; }
public override bool ValidateUser(string username, string password)
{
var cust = repository.GetAllCustomers().SingleOrDefault..
When I run the application normally i.e. not testing, the login works fine. In the application I inject the CustomerRepository into the custom membership provider in Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
private IKernel _kernel = new StandardKernel(new MyNinjectModules());
internal class MyNinjectModules : NinjectModule
{
public override void Load()
{
Bind<ICustomerRepository>().To<CustomerRepository>();
}
}
protected void Application_Start()
{
_kernel.Inject(Membership.Provider);
...
Is it the case that the Global.asax code isn't run while unit testing? and so my custom provider isn't being injected, hence the fail?
UPDATE
I mocked my Provider class and passed the mocked CustomerRepository object to it.
Mock<AccountMembershipProvider> provider = new Mock<AccountMembershipProvider>();
provider.Object.repository = mockCustomerRepository.Object;
I then created a setup for the method I'm trying to test:
mockCustomerRepository.Setup(m => m.IsValidLogin("me#5.com", "password")).Returns(true);
But unfortunately I'm still getting a fail every time. To answer the question about whether I need a real or mocked object for the test - I'm not fussy, I just want to get it working at the moment!
UPDATE 2
I made those changes, and while it's still failing, it has allowed me to identify the specific problem. While debugging the test, I discovered that when I call the overridden
Membership.ValidateUser(LoginModel.Email, LoginModel.Password)
The Membership.Provider is of type SqlMembershipProvider (which is presumably the default type) and consequently validation fails.
If I cast the provider to my custom provider...
((AccountMembershipProvider)Membership.Provider).ValidateUser(LoginModel.Email, LoginModel.Password)
I get an InvalidCastException when running the test. So it seems that my mocked AccountMembershipProvider isn't being used for the test and instead the default provider is being used.
I think you have identified this already in the comment:
// set your mock provider in your AccountController
However I'm not sure what you mean exactly - I don't have a property on my AccountController to assign the provider to, and i'm not injecting it into the constructor.

Your original question:
"Is it the case that the Global.asax code isn't run while unit testing? and so my custom provider isn't being injected, hence the fail?"
My answer:
Yes.
The global.asax file is used by ASP.Net and ISS at run-time. It is compiled when the server receives it's first request.
When you are testing, you aren't in the context of a ASP.Net web-application running in ISS, but rather in program running in a test session. This means your global.asax won't get called.
More importantly, when you call:
Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
Ninject won't get called the fill the import. Moq will create a mock based on the interface. No real object will be created.
Since you did not define any Setup methods, ie:
mockCustomerRepository.Setup(mock => mock.MyAuthenticateMethod()).Returns(true);
You are passing around a mock with no defined behaviour. By default these will return false. Which probably explains why you are always getting a viewresult.
What you need to do is define setup methods for the methods you need to mock.
These are the methods of CustomerRepository that will get called you when call:
target.LogIn(model);
Also note that your AccountMembershipProvider won't get it's CustomerRepository injected since NInject won't be used. If you are testing the AccountController and it's not static (Moq doesn't work with static) you should consider mocking the AccountMembershipProvider. If you can't, then you would need to supply your mocked instance of CustomerRepository to AccountMembershipProvider.repository in your tests.
Another solution, instead of creating a Moq mock, you could also manually create (with new) a real instance of CustomerRepository in your test.
You could have Ninject do it, but at this point why? You can create it yourself and you know what specific type to create.
It all boils down to if you need a mock or a real instance of the object for this test.
Update:
If your provider is mocked, there is no need to set the repository on it. When you are calling a mock, the real object won't get called.
What you need to do is something like this:
Mock<AccountMembershipProvider> provider = new Mock<AccountMembershipProvider>();
// set your mock provider in your AccountController
provider.Setup(m => m.ValidateUser("me#5.com", "password")).Returns(true);
Update 2:
I think you are pretty close to making your test work. Without seeing all of your code (test and class under test) I can't really give you anymore help. I also feel I answered your original question, but if you are still stuck you might get more help by asking a new question relating to the problem you are currently tackling.

In your code you only create controller, but not run initialization for membership. I recommend you to create your own UserService with method ValidateUser and other you need instead of static class Membership usage.

Related

How to make Ninject return a mock object

I have a code that looks like this
public class EmployeeController : Controller
{
public ContextWrapper contextWrapper;
public EmployeeController (IContextWrapper wrapper)
{
contextWrapper = wrapper;
}
In my dependency resolver I have the binding for IContextWrapper
kernel.Bind<IContextWrapper>().To<ContextWrapper>();
The implementation of ContextWrapper has an object which is of type Linq DataContext.
public class ContextWrapper : IContextWrapper
{
public MyDataContext dataContext;
public ContextWrapper(MyDataContext context)
{
this.dataContext = context;
}
Now my action method in this controller looks like this
var empRepository = new EmployeeRepository(contextWrapper);
//do some tests with this repository.
some values = contextWrapper.datacontext.get some values from the database table
//do some tests with these values.
To be able to test this method
I should be able to provide some sort of mock database(not literally) or
make the contextWrapper.datacontext return mocked values or
I even thought of creating another implementation of the IContextWrapper that doesn't use a Linq DataContext object. And creating another constructor for this controller and pass that fake implementation. Also in my dependency resolver I would bind the fake object to the IContextWrapper. Although I do not know how to make Ninject
As a last resort test my method against a test database since it all boils down to this Linq DataContext object and it seems I cannot get rid of it past a certain level.
Problem is the more I read about it, more I get confused. I have tried to give as much detail as possible to explain my problem. If any one has a clear cut idea about how to get this, please suggest.

Problems After Disposing DbContext

I recently made changes to my MVC3 Application in attempt to properly dispose of the DbContext objects [1]. This worked great in development, but once the application was pushed to my production server, I started intermittently getting some funny exceptions which would persist until the AppPool was recycled. The exceptions can be traced back to code in my custom AuthorizeAttribute and look like:
System.InvalidOperationException: The 'Username' property on 'User' could not be set to a 'Int32' value. You must set this property to a non-null value of type 'String'.
System.InvalidOperationException: The 'Code' property on 'Right' could not be set to a 'String' value. You must set this property to a non-null value of type 'Int32'.
(Database schema looks like this: Users: [Guid, String, ...], Rights: [Guid, Int32, ...])
It is as if some "wires are getting crossed", and the application is mixing up results from the database: trying to materialize the Right result as a User and vise versa.
To manage the disposal of DbContext, I put code in to store this at a per-controller level. When the controller is disposed, I dispose the DbContext as well. I know it's hacky, but the AuthorizeAttribute uses the same context via filterContext.Controller.
Is there something wrong with handling the object lifecycle of DbContext in this manor? Are there any logical explanations as to why I am getting the crisscross exceptions above?
[1] Although I understand that it is not necessary to dispose of DbContext objects, I recently came across a number of sources stating that it was best practice regardless.
Edit (per #MikeSW's comment)
A property of the AuthorizeAttribute representing the DbContext is being set in the OnAuthorization method, when the AuthorizationContext is in scope. This property is then later used in the AuthorizeCore method.
Do you actually need to dispose the context?
According to this post by Jon Gallant who has been in touch with the Microsoft ADO.NET Entity Framework team:
Do I always have to call Dispose() on my DbContext objects? Nope
Before I talked with the devs on the EF team my answer was always a resounding “of course!”. But it’s not true with DbContext. You don’t need to be religious about calling Dispose on your DbContext objects. Even though it does implement IDisposable, it only implements it so you can call Dispose as a safeguard in some special cases. By default DbContext automatically manages the connection for you.
First i recommend that you get "really" familiar with
ASP.NET Application Life Cycle Overview for IIS 7.0 as it's fundamental to good MVC application design.
Now to try and "mimic" your code base
Let's say you have a similar custom MembershipProvider as described here https://stackoverflow.com/a/10067020/1241400
then you would only need a custom Authorize attribute
public sealed class AuthorizeByRoles : AuthorizeAttribute
{
public AuthorizeByRoles(params UserRoles[] userRoles)
{
this.Roles = AuthorizationHelper.GetRolesForEnums(userRoles);
}
}
public static class AuthorizationHelper
{
public static string GetRolesForEnums(params UserRoles[] userRoles)
{
List<string> roles = new List<string>();
foreach (UserRoles userRole in userRoles)
{
roles.Add(GetEnumName(userRole));
}
return string.Join(",", roles);
}
private static string GetEnumName(UserRoles userRole)
{
return Enum.GetName(userRole.GetType(), userRole);
}
}
which you can use on any controller or specific action
[AuthorizeByRoles(UserRoles.Admin, UserRoles.Developer)]
public class MySecureController : Controller
{
//your code here
}
If you want you can also subscribe to the PostAuthorizeRequest event and discard the results based on some criteria.
protected void Application_PostAuthorizeRequest(Object sender, EventArgs e)
{
//do what you need here
}
As for the DbContext, i have never run into your situation and yes per request is the right approach so you can dispose it in the controller or in your repository.
Of course it's recommended that you use filters and then add [AllowAnonymous] attribute to your actions.

Getting property from injected type during registration

Hopefully I can explain this to where someone might understand it enough to help :)
Anyways, I want to take a property from an injected type and use that in another injection. So imagine you have MVC model state on a controller that you want to inject into a service the controller uses.
public class MyController
{
public MyController(IService service)
{
....
}
}
public class MyService : IService
{
public MyService(IModelStateWrapper modelState)
{
....
}
}
How can I accomplish basically this:
public class MyController
{
public MyController(IService service)
{
service.ModelState = new ModelStateWrapper(ModelState);
}
}
Using an injection with Autofac or whatever DI container.
You can do this, but you have to unravel a couple of design problems before it's possible.
First, it appears that your IService implementation requires you pass the IModelStateWrapper in during construction only to be overwritten later during the creation of the controller. You have to make it so the IService implementation only has it as a property, not as a constructor requirement.
Second, you have to make sure it's OK that the service.ModelState setting happens just after construction of the controller. If there is other constructor logic that assumes the service.ModelState is set, then you have something that can't really be done via DI.
If you do that unraveling, Autofac will let you do some pretty cool stuff. When you register your controller type, register a lambda instead of just a type.
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>();
builder.Register(
c=>
{
var service = c.Resolve<IMyService>();
var controller = new MyController(service);
service.ModelState = new ModelStateWrapper(controller.ModelState);
return controller;
}).As<IController>();
var container = builder.Build();
Note the circular logic thing is handled in the lambda of the registration. Now when you resolve a controller...
var controller = container.Resolve<IController>();
...that logic will run and you'll get the effect you're looking for.
Again, I'll voice some concern over the circular reference stuff going on here. If there's a way to remove that circular dependency between the controller and the service, you'd be in a better spot to let DI work for you.

Is there a better way to use Structuremap to inject dependencies into a custom RoleProvider?

I found http://www.devproconnections.com/content1/catpath/database-development/topic/a-perfect-storm-linq-to-sql-dependency-injection-and-asp-net-providers/page/2 and had similar code as from the webpage:
public class CustomProvider : MembershipProvider, IMembershipProvider
{
private IUserRepository _userRepo;
// this .ctor is used via unit tests (as a seam)
public CustomProvider(IUserRepository repo)
{
this._userRepo = repo;
}
// requisite parameter-less constructor:
public CustomProvider()
{
// do NOTHING here
}
public override bool ValidateUser(string username, string password)
{
// HACK:
IUserRepository repo = this._userRepo ?? ObjectFactory.GetInstance<IUserRepository>();
SiteUser user = repo.GetUserByEmailAddress(username.ToLower());
if (user == null)
return false;
if (!user.Active || !user.Verified)
return false;
if (user.PassPhrase.IsNullOrEmpty())
return false;
// do other verification... etc
}
}
Except mine is a custom RoleProvider. Is calling the ObjectFactory.GetInstance an accepted way to inject dependencies into a RoleProvider? I tried to setup a property to inject the dependency, but I could not get that to work. I'm sure my StructureMap registry is wrong. But hard to find out the right way when the documentation is out of date.
So for an ASP.NET MVC3 app, is calling the ObjectFactory ok in a custom RoleProvider? Or should I attempt to inject to a property?
If a property, how? I have For<RoleProvider>().Use(ctx => Roles.Provider); currently. But I'm not sure id the Use should be an Add, nor am I sure on the syntax to inject a dependency into a property.
Still Need help
I'm having an awful time trying to make miniprofiler not throw Null ref exceptions when I merely move the StructureMap ObjectFactory to a property for init. The goal is to allow roles to be cached. I get the same error as these questions mini-profiler nullreferenceexception Help Configure mvc mini profiler with Linq to Sql
I've updated to the latest MVCMiniProfiler and tried it's MVC package. Seems that profiling isn't enabled before the custom RoleProvider is init or the properties are initialized. If I set the field straight from the overridden GetRolesForUser method, everything is fine. If I make that field a backer to a public property, I get NULL exceptions in ProfiledDbCommand. Why?
The Microsoft "provider" pattern does not work well with dependency injection, because of its reliance on statics and singletons. If you have to use a Provider, just do the service location via ObjectFactory.GetInstance and move on.

RhinoMocks: Correct way to mock property getter

I'm new to RhinoMocks, and trying to get a grasp on the syntax in addition to what is happening under the hood.
I have a user object, we'll call it User, which has a property called IsAdministrator. The value for IsAdministrator is evaluated via another class that checks the User's security permissions, and returns either true or false based on those permissions. I'm trying to mock this User class, and fake the return value for IsAdministrator in order to isolate some Unit Tests.
This is what I'm doing so far:
public void CreateSomethingIfUserHasAdminPermissions()
{
User user = _mocks.StrictMock<User>();
SetupResult.For(user.IsAdministrator).Return(true);
// do something with my User object
}
Now, I'm expecting that Rhino is going to 'fake' the call to the property getter, and just return true to me. Is this incorrect? Currently I'm getting an exception because of dependencies in the IsAdministrator property.
Can someone explain how I can achieve my goal here?
One quick note before I jump into this. Typically you want to avoid the use of a "Strict" mock because it makes for a brittle test. A strict mock will throw an exception if anything occurs that you do not explicitly tell Rhino will happen. Also I think you may be misunderstanding exactly what Rhino is doing when you make a call to create a mock. Think of it as a custom Object that has either been derived from, or implements the System.Type you defined. If you did it yourself it would look like this:
public class FakeUserType: User
{
//overriding code here
}
Since IsAdministrator is probably just a public property on the User type you can't override it in the inheriting type.
As far as your question is concerned there are multiple ways you could handle this. You could implement IsAdministrator as a virtual property on your user class as aaronjensen mentioned as follows:
public class User
{
public virtual Boolean IsAdministrator { get; set; }
}
This is an ok approach, but only if you plan on inheriting from your User class. Also if you wan't to fake other members on this class they would also have to be virtual, which is probably not the desired behavior.
Another way to accomplish this is through the use of interfaces. If it is truly the User class you are wanting to Mock then I would extract an interface from it. Your above example would look something like this:
public interface IUser
{
Boolean IsAdministrator { get; }
}
public class User : IUser
{
private UserSecurity _userSecurity = new UserSecurity();
public Boolean IsAdministrator
{
get { return _userSecurity.HasAccess("AdminPermissions"); }
}
}
public void CreateSomethingIfUserHasAdminPermissions()
{
IUser user = _mocks.StrictMock<IUser>();
SetupResult.For(user.IsAdministrator).Return(true);
// do something with my User object
}
You can get fancier if you want by using dependency injection and IOC but the basic principle is the same across the board. Typically you want your classes to depend on interfaces rather than concrete implementations anyway.
I hope this helps. I have been using RhinoMocks for a long time on a major project now so don't hesitate to ask me questions about TDD and mocking.
Make sure IsAdministrator is virtual.
Also, be sure you call _mocks.ReplayAll()
_mocks.ReplayAll() will do nothing. It is just because you use SetupResult.For() that does not count. Use Expect.Call() to be sure that your code do everything correct.

Resources