c# - How to fake or mock user logging in (authentication) with ASP.NET MVC for functional testing -


i'm building custom permissions system asp.net mvc, because authorization system comes mvc isn't flexible enough our needs. includes mvc area that's packaged dll along views, css , javascript. have unit tests already, i'm trying create functional tests through browser. these functional tests run locally computer or on continuous integration server.

the permissions system i'm building doesn't authentication. handles authorization. ideally i'd fake user log-ins each test. create user session arbitrary usernames , passwords instead of keeping separate table of users passwords, , authenticating against that.

i tried setting genericprincipal object in session in accountcontroller, , setting httpcontext.current.user before each request, request seen unauthenticated:

accountcontroller

[authorize] public class accountcontroller : controller {     //     // post: /account/login     [httppost]     [allowanonymous]     [validateantiforgerytoken]     public actionresult login(loginviewmodel model, string returnurl)     {         if (modelstate.isvalid)         {             formsauthentication.setauthcookie(model.username, model.rememberme);              // add fake user current session global.asax can set             // user on current httpcontext mock object. (see             // global.asax, application_acquirerequeststate)             httpcontext.session["currentuser"] = new genericprincipal(new genericidentity(model.username), new string[0]);              if (url.islocalurl(returnurl))                 return redirect(returnurl);              return redirecttoaction("index", "home");         }          modelstate.addmodelerror(string.empty, "username or password incorrect");          return view(model);     } } 

global.asax

public class mvcapplication : system.web.httpapplication {     protected void application_acquirerequeststate(object sender, eventargs e)     {         if (httpcontext.current.session != null)         {             // try mock user session, set in             // accountcontroller.login...             httpcontext.current.user = httpcontext.current.session["currentuser"] iprincipal;         }     } } 

i created custom authorize attribute used in mvc controllers:

public class permissionlevelattribute : system.web.mvc.authorizeattribute {     public override void onauthorization(authorizationcontext filtercontext)     {         if (!filtercontext.httpcontext.request.isauthenticated || currentprincipal == null)         {             base.onauthorization(filtercontext);              return;         }          // custom permissions logic...     } } 

example usage of attribute in controller:

public class blogpostscontroller : controller {     [permissionlevel(roles="blogs.posts.edit.update")]     public actionresult edit(int id)     {         // ...     } } 

when this, filtercontext.httpcontext.request.isauthenticated property false, , bails out of onauthorization method.


how fake or mock user login in asp.net mvc creates httpcontext.current.session object , sets httpcontext.current.user?

this solution doesn't create "mock" user creates fake user , doesn't check username , password. this, you'll need make 2 major changes:

  1. rewrite accountcontroller doesn't check username , password

    [authorize] public class accountcontroller : controller {     //     // get: /account/login     [allowanonymous]     public actionresult login(string returnurl)     {         viewbag.returnurl = returnurl;         return view();     }      //     // post: /account/login     [httppost]     [allowanonymous]     [validateantiforgerytoken]     public actionresult login(loginviewmodel model, string returnurl)     {         if (modelstate.isvalid)         {             formsauthentication.setauthcookie(model.username, model.rememberme);              if (url.islocalurl(returnurl))                 return redirect(returnurl);              return redirecttoaction("index", "home");         }          modelstate.addmodelerror(string.empty, "username or password incorrect");          return view(model);     }      //     // get: /account/logoff     public actionresult logoff()     {         formsauthentication.signout();          return redirecttoaction("index", "home");     } } 
  2. remove or comment out owin related config settings in web.config:

    <configuration>   <system.webserver>     <modules>       <!--<remove name="formsauthentication" />-->     </modules>   </system.webserver>   <runtime>     <assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">       <!--<dependentassembly>         <assemblyidentity name="microsoft.owin.security" publickeytoken="31bf3856ad364e35" />         <bindingredirect oldversion="0.0.0.0-3.0.1.0" newversion="3.0.1.0" />       </dependentassembly>       <dependentassembly>         <assemblyidentity name="microsoft.owin.security.oauth" publickeytoken="31bf3856ad364e35" />         <bindingredirect oldversion="0.0.0.0-3.0.1.0" newversion="3.0.1.0" />       </dependentassembly>       <dependentassembly>         <assemblyidentity name="microsoft.owin.security.cookies" publickeytoken="31bf3856ad364e35" />         <bindingredirect oldversion="0.0.0.0-3.0.1.0" newversion="3.0.1.0" />       </dependentassembly>       <dependentassembly>         <assemblyidentity name="microsoft.owin" publickeytoken="31bf3856ad364e35" />         <bindingredirect oldversion="0.0.0.0-3.0.1.0" newversion="3.0.1.0" />       </dependentassembly>-->     </assemblybinding>   </runtime> </configuration> 

this allow log in arbitrary user password.

important: wouldn't production version of web application, obviously. building mvc area nuget package , installing package on clean mvc project write automated tests against integrated nuget package , mvc application. that's why able use solution.


Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

javascript - Get parameter of GET request -

javascript - Twitter Bootstrap - how to add some more margin between tooltip popup and element -