I wrote a custom RequestValidator implementation to deal with W.I.F. security tokens. Now I am trying to write a unit test for this class. It's turning out to be more difficult that I anticipated.
1. This method is protected internal. Even using InternalsVisibleToAttribute, I am having no luck being able have my unit test compile against my implementation of:
bool
IsValidRequestString(HttpContext context,
string value, RequestValidationSource rvs,
string
collectionKey, out
int validationFailureIndex)
2. The HttpContext class used by this method is sealed so I am not sure how to mock one up with a mocking framework (i.e. rhinomocks in my case).
Anyone have any tips for making the RequestValidator testable?
The problem is that the base asp.net class RequestValidator wants a real HttpContext (not HttpContextBase) and HttpContext is a sealed class so it can't be mocked / faked.
That would work as far as exposing the call to the unit test (#1). Unfortunately, the HttpContext is a sealed class (#2) and therefore can't be mocked / faked to contain the necessary Form data.
Sorry, that second method should have had an HttpContextBase instead of an HttpContext. (Which is why the first method wraps the current context in an HttpContextWrapper.) You can definitely mock that. :)
I've updated the sample.
Marked as answer by ricka6 on Jul 10, 2010 01:50 AM
HttpContextBase can be mocked but the stinker is that I have no control over how the RequestValidator gets called at actual runtime. It gets registered with ASP.NET via web.config like so:
<!-- Updated custom request validation to better handle token post backs -->
Yes, but that's fine, since the overload that takes an HttpContext just immediately turns around and calls the overload that takes an HttpContextBase. Therefore if you unit test the method that takes an HttpContextBase, you don't need to unit test the method
that takes an HttpContext.
Marked as answer by ricka6 on Jul 10, 2010 01:50 AM
skmcfadden
Member
35 Points
97 Posts
unit testing custom RequestValidator?
Jun 30, 2010 01:06 AM|LINK
I wrote a custom RequestValidator implementation to deal with W.I.F. security tokens. Now I am trying to write a unit test for this class. It's turning out to be more difficult that I anticipated.
1. This method is protected internal. Even using InternalsVisibleToAttribute, I am having no luck being able have my unit test compile against my implementation of:
bool IsValidRequestString(HttpContext context, string value, RequestValidationSource rvs, string collectionKey, out int validationFailureIndex)
2. The HttpContext class used by this method is sealed so I am not sure how to mock one up with a mocking framework (i.e. rhinomocks in my case).
Anyone have any tips for making the RequestValidator testable?
thanks
Request Validation unit test
ignatandrei
All-Star
134491 Points
21566 Posts
Moderator
MVP
Re: unit testing custom RequestValidator?
Jun 30, 2010 07:14 AM|LINK
http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
skmcfadden
Member
35 Points
97 Posts
Re: unit testing custom RequestValidator?
Jun 30, 2010 04:55 PM|LINK
The problem is that the base asp.net class RequestValidator wants a real HttpContext (not HttpContextBase) and HttpContext is a sealed class so it can't be mocked / faked.
HttpContextext sealed
levib
Star
7702 Points
1099 Posts
Microsoft
Re: unit testing custom RequestValidator?
Jun 30, 2010 04:59 PM|LINK
protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource rvs, string collectionKey, out int validationFailureIndex) { return IsValidRequestStringPublic(new HttpContextWrapper(context), value, rvs, collectionKey, out validationFailureIndex); } public bool IsValidRequestStringPublic(HttpContextBase context, string value, RequestValidationSource rvs, string collectionKey, out int validationFailureIndex) { // actual logic goes here }</div><div></div><div>Then just call the second method (the one containing the actual logic) from your unit test.</div>
skmcfadden
Member
35 Points
97 Posts
Re: unit testing custom RequestValidator?
Jun 30, 2010 05:05 PM|LINK
That would work as far as exposing the call to the unit test (#1). Unfortunately, the HttpContext is a sealed class (#2) and therefore can't be mocked / faked to contain the necessary Form data.
HttpContextext sealed
levib
Star
7702 Points
1099 Posts
Microsoft
Re: unit testing custom RequestValidator?
Jun 30, 2010 05:12 PM|LINK
Sorry, that second method should have had an HttpContextBase instead of an HttpContext. (Which is why the first method wraps the current context in an HttpContextWrapper.) You can definitely mock that. :)
I've updated the sample.
skmcfadden
Member
35 Points
97 Posts
Re: unit testing custom RequestValidator?
Jun 30, 2010 05:23 PM|LINK
HttpContextBase can be mocked but the stinker is that I have no control over how the RequestValidator gets called at actual runtime. It gets registered with ASP.NET via web.config like so:
<!-- Updated custom request validation to better handle token post backs -->
<httpRuntime requestValidationType="Acme.Apps.Web.Utilities.Impl.WsFederationRequstValidator, Acme.Apps.Web.Utilities.Impl" />
So ASP.NET will always call the overload with the real HttpContext and not the HttpContextBase.
<div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> <!-- Updated custom request validation to better handle token post backs --></div> <div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste"> <httpRuntime requestValidationType="CT.iMagio2.Apps.Web.Utilities.Impl.WsFederationRequstValidator, CT.iMagio2.Apps.Web.Utilities.Impl" /></div>HttpContextext sealed
levib
Star
7702 Points
1099 Posts
Microsoft
Re: unit testing custom RequestValidator?
Jun 30, 2010 05:32 PM|LINK
Yes, but that's fine, since the overload that takes an HttpContext just immediately turns around and calls the overload that takes an HttpContextBase. Therefore if you unit test the method that takes an HttpContextBase, you don't need to unit test the method that takes an HttpContext.
skmcfadden
Member
35 Points
97 Posts
Re: unit testing custom RequestValidator?
Jun 30, 2010 06:52 PM|LINK
Just gave that a try. It wouldn't compile.
<div style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;" id="_mcePaste">Error 108 Argument 1: cannot convert from 'System.Web.HttpContext' to 'System.Web.HttpContextBase' C:\Dev\TFS\CT\iMagio2\Apps\Web\Utilities\Impl\WsFederationRequestValidator.cs 19</div> <div></div>Error 108 Argument 1: cannot convert from 'System.Web.HttpContext' to 'System.Web.HttpContextBase'
Looks like it may because there is no relationship between HttpContext and HttpContextBase:
public sealed class HttpContext : IServiceProvider
public abstract class HttpContextBase : IServiceProvider
HttpContextext sealed
levib
Star
7702 Points
1099 Posts
Microsoft
Re: unit testing custom RequestValidator?
Jun 30, 2010 06:59 PM|LINK
Remember - you need to wrap the HttpContext inside an HttpContextWrapper (which subclasses HttpContextBase). Look closely at the sample.