Unit testing with dependency on HttpContext - c#

I need to test some static methods that rely on the current context. Now, I can certainly use the HttpContextWrapper to remove this dependency from my own code. The problem lies with the 3rd party API I am using in these methods. THEY are relying on the HttpContext and so I can't do anything about that. However, what I'm trying to do is set the HttpContext with my HttpContextBase.
So my code looks something like this:
public static bool IsSignedUpUser()
{
//This calls IsSignedUpUser with the production context
return IsSignedUpUser(new HttpContextWrapper(HttpContext.Current));
}
public static bool IsSignedUpUser(HttpContextBase context)
{
HttpCookie objCookie = SomeExternalAPIThatReliesOnHttpContextBeingSet();
return (objCookie != null)
}
What I want to do is something like:
HttpContext.Current = context; //where context is a mocked HttpContextBase
This way when the 3rd party API is looking in the HttpContext for querystring, cookie values, etc, it doesn't throw a NullReferenceException.
Why isn't this a dupe?
In the code in the question referenced as a dupe, the author looks to be in complete control with no external dependencies. I'm using third party libraries that have a dependency on HttpContext, I can't change their method signatures to accept HttpContextBase so I need a way to assign my HttpContextBase to HttpContext.
If this is not possible, and so far I am lead to believe that it isn't, then good answers should suggest how to remove these dependencies. 500 - Internal Server Error has at least one good suggestion.

In my view, you should be replacing the call to SomeExternalAPIThatReliesOnHttpContextBeingSet with a custom interface method that you inject and which can then be mocked as any other.

[EDIT] Per #jessehouwing, "Moles" is now "Fakes", which should improve your Google-fu
Ah, static dependencies...the worse kind.
It may be overkill, but I would look into perhaps using Moles (or whatever the heck they renamed it to), which will let you override ANY behavior, static, sealed or otherwise; here are some links to peruse:
Mocking the Unmockable
The Moles Framework
Unit Testing with Moles
A different "Mocking the Unmockable"

Related

Attach an object to the pipeline without DI on ASP.NET 5 (or extending HttpContext)

tl;dr
.- Is there a way to include a property (extend) on the HttpContext of a custom class, the same as there's a User property which is a ClaimsPrincipal? I want to access HttpContext.MyOwnProperty of a custom class along all the pipeline (without DI).
Long explanation:
I've created my own identity system on ASP.NET 5 to get rid of the framework's umpteenth and ever-changing Identity System, of which I'm really tired of, and to get away of the use of claims, which could be very standardized but are also inefficient where you come to lot of them.
I use a typed object for representing a user access, and obtain it from an in memory (or from a shared caché) repository which is a service registered early on the pipeline, somehow as the current UserManager. Then I pass this object to the pipeline by means of mapping it's properties to a scoped service that I've registered previously:
services.AddSingleton<AccessManager>();
services.AddScoped<CurrentAccess>();
Everything is working fine but I'm wondering if there would be a more efficient way to attach the CurrentAccess object to the pipeline, other than having to inject and resolve it on every place, since it's broadly used in the application.
The goal is to extend the HttpContext class to add a property of the CurrentAccess type, the same as there is a User property wich is a ClaimsPrincipal. That would be great, but I don't know how to do it. Any idea out there?
(I've also tried another approach that is using the HttpContext.Items property, which is a Dictionary<object, object> where I can add my own object, but I don't know it's lifecycle and I would have to look for my item and cast it every time, what seems uglier than the previous option)
Keep registering your services the same way you are doing.
services.AddSingleton<AccessManager>();
services.AddScoped<CurrentAccess>();
Then create an HttpContext.GetCurrentAccess extension method that returns the CurrentAccess object:
public static class HttpContextExtensions
{
public static CurrentAccess GetCurrentAccess(this HttpContext httpContext)
{
return httpContext.RequestServices.GetRequiredService<CurrentAccess>();
}
}
This way, you can use the extension method as a convenience method in places where you don't want to a CurrentAccess dependency to be injected in the constructor.
public IActionResult Index()
{
var currentAccess = this.Context.GetCurrentAccess();
...
return View();
}
Where makes sense to take a dependency take it, in other places use the convenience extension method.
Is there a way to include a property (extend) on the HttpContext of a custom class, the same as there's a User property wich is a ClaimsPrincipal? I want to access HttpContext.MyOwnProperty of a custom class along all the pipeline (without DI).
You can't add properties to a class. That would be an awesome C# feature though :).

Can I mock a private method or what is the correct way to test this POST method?

I have an existing ASP.NET MVC app and wanted to create some unit tests and I quickly ran into the problem below. Is there some sort of way to use MOQ and say 'When the private method GETCLIENTIP is run then return 'xxx'')?
Since right now it is uses parts of HttpContext that of course the unit test does not have.
public HttpResponseMessage Post([FromBody]TriageCase TriageCase)
{
if (ModelState.IsValid)
{
//Get the IP address from the request
TriageCase.ipAddress = this.GetClientIP(Request);
_log.Info("IP Address = " + TriageCase.ipAddress);
}
}
public void Verify_Not_A_Suicide()
{
TriageCaseRepository repository = new TriageCaseRepository();
var controller = new TriageCasesController(repository);
//This will not work because I must mock a private method in the controller?
HttpResponseMessage result = controller.Post(new TriageCase());
}
There are several ways to do this, right from nasty complicated ones to simple traded-off ones. here are some:
you could make the GetClientIP method agnostic of HttpContext. and then make it internal. mark the controller assembly with InternalsVisibleTo and put the unit test assembly path.
making the method agnostic of HttpContext saves you from having a HttpContextBase (the abstract http context class from 3.5 onwards for to enable testing) and provide mocking etc. (btw, you should think about it. especially for MVC) pass the specific string as the parameter to the method. e.g. The specific server variable string.
you could make the GetClientIP method receive HttpContextBase as the parameter and then make it internal. mark the controller assembly with InternalsVisibleTo and put the unit test assembly path.
in your controller action, you need to call this method as this.GetClientIP(new HttpContextWrapper(HttpContext.Current))
your unit tests can set mockable context. and whats more, you can set expectations on the context as to if the Request property was called, or if the ip address related server variable call was made. (not to mention the straight ip address value verification)
you could use FakeItEasy or Microsoft Moles etc. to create private accessors for private methods. i normally refrain from that.
you could write an interface base INetworkUtility which has a method to give you the IP Address. your controller could use this interface. and it could be tested in isolation as well.
you could have a public helper class to get the ip address, which can be unit tested.
as you can see, every solution has some trade-off you need to do.
getting IP Address from the Request object is an isolated piece of logic irrespective of mvc or web api or asp web forms. (still web specific though) so it doesn't harm to have it as helper methods or interface based helper methods.
personally, i prefer the Internal approach, (since it is almost private) and doesn't need much code change.
In proper TDD fashion you don't Unit Test "private" or "internal" methods. Only the public interface is used within Unit Tests. If you Unit Test a private/internal method then you are tying your unit tests too tightly to that specific implementation.
What should be done instead is use Dependency Injection to inject a class/interface that implements the "dependent" functionality that you are needing to unit test. This will help further modularize your code thus making it easier to maintain.
I general don't try to test private methods. It just gets messy - test the input and output of an action...
Either do the Dependency Injection thing or think about a "test double" or "accessor" class...
For a test double - make the private method a protected and then you inherit the controller and manually mock out inputs or outputs as required. I am not stating whether this is better or worse than Ioc, I am saying this is another way to do it.
protected virtual string ExecuteIpnResponse(string url)
{
var ipnClient = new WebClient();
var ipnResponse = ipnClient.DownloadString(url);
return ipnResponse;
}
I did a post on this testing style recently for checking a paypal call.
http://viridissoftware.wordpress.com/2014/07/29/paypal-ipn-payment-notification-example-in-c/

Attempt to resolve item from Ninject in IInterceptor fails

I am attempting to use Ninject on my current project, and up to now, have been loving it. I am in the middle of attempting to configure an IInterceptor object to intercept and handle a failed method call to my service layer. This is hosted in an ASP.NET MVC 5 application.
In the IInterceptor, I've tried several things, such as:
Setting private variables using constructor injection, but came to discover that it appears Ninject will reuse an IInterceptor instance for a method indefinitely, and I haven't found a way to stop that. Since one of the things I bring into scope is a DbContext which gets disposed elsewhere, it ends up failing on any future requests than the one it was created on.
I found that the IInvocation has a Request.Kernel property. However, when I attempt to resolve my UOW from the container, which is .InRequestScope(), it fails, since it attempts to resolve the IUowService dependencies, (one of the dependencies depends on the HttpContext which is null at this point), but appears to be doing so outside the Request scope. It is ignoring the fact that the dependencies it needs have already been created within the ASP.NET request, and is attempting to create new ones.
Setting a binding for the interceptor this.Bind<NinjectExceptionHandler>().ToSelf().InTransientScope(), yet this didn't seem to stop the caching of the interceptor.
I imagine there is something I am missing. I understand wanting to cache IInterceptor objects for performance, but I find it irksome that I can't easily use the IOC container or Injection to get the objects I need for my request.
This is the last issue I am having with getting interception up and running as I need, so any help is greatly appreciated!
Per your request i'm going into more detail on how we've achieved "1 proxy : 1 interceptor" instance relation ship.
We've taken the easy way which does not offer as much flexibility as what the official ninject interception extensions offers. We are relying directly on castle.core dynamic proxy and thus castle's IInvocation interface.
(Please not the code below is for a proxy without target, but a proxy with target is quite similar -- the only thing which changes is that you'll need to know the target class type and use IResolutionRoot.Get<TargetClassType>() to instanciate it).
Basically we created a binding like:
IBindingRoot.Bind<IFoo>()
.ToProvider<InterfaceProxyWithoutTargetProvider<IFoo>>();
Now of course we need to know which interceptors the proxy shall use. Again we are using an easy - and not so nice - design:
public interface IInterceptorBindingDefinition<TTarget>
{
Type InterceptorType { get; }
}
public class InterceptorBindingDefinition<TTarget, TInterceptor> : IInterceptorBindingDefinition<TTarget>
where TInterceptor : IInterceptor
{
Type InterceptorType { get { return typeof(TInterceptor); } }
}
IBindingRoot
.Bind<IInterceptorBindingDefinition<IFoo>>()
.To<InterceptorBindingDefinition<TTarget, LoggingInterceptor>();
IBindingRoot
.Bind<IInterceptorBindingDefinition<IFoo>>()
.To<InterceptorBindingDefinition<TTarget, SomeOtherInterceptor>();
This means IFoo shall get two interceptors: LoggingInterceptor and SomeOtherInterceptor.
and the implementation of the provider:
public class InterfaceProxyWithoutTargetProvider<TInterface> : IProvider<TInterface>
where TInterface : class
{
private readonly IProxyGenerator proxyGenerator;
private readonly IInterceptorFactory interceptorFactory;
public InterfaceProxyWithoutTargetProvider(IProxyGenerator proxyGenerator, IInterceptorFactory interceptorFactory)
{
this.proxyGenerator = proxyGenerator;
this.interceptorFactory = interceptorFactory;
}
public Type Type
{
get { return typeof(TInterface); }
}
public object Create(IContext context)
{
var interceptorTypes = context.Kernel.Get<IEnumerable<IInterceptorBindingDefinition<TInterface>>();
IList<IInterceptor> interceptors = interceptorTypes
.Select(x => x.InterceptorType)
.Select(x => context.ContextPreservingGet(x))
.ToList();
return this.proxyGenerator.CreateInterfaceProxyWithoutTarget<TInterface>(interceptors);
}
}
Now of course we polished the thing a little bit so we have a fluent syntax configuring the binding of the proxy and the interceptor - which is easy enough.
However ninject.extensions.interception's approach with its IAdviceRegistry and IAdvice is certainly better (but also requires more insight into how ninject works).
So it appears that there is no way to do what I was trying gracefully with Ninject. Once in the IInterceptor and in the later parts of async operations, the HttpContext was lost and Ninject couldn't resolve things that really it should have thought were in scope. Coupled with the fact that it reused IInterceptor's for a method (like I said, understandable, but irritating), I just couldn't get it to work right as I wanted to.
What I was able to do to get around the fact was something simple, yet a little kludgy (I think). Since all the methods that I was intercepting were in my service layer, and all my services implemented a IBaseService through a BaseService abstract base class, which happened to have the objects I needed as properties, I was able to do this in the interceptor:
var uow = (invocation.Request.Target as IBaseService).UnitOfWork;
This allowed me to access my unit of work and Fail it, as well as access the logging instance I was working on.
While this works, I would like to see someway to get interceptor constructor injection working correctly through multiple calls, or calls to the Kernel further down the line to realize that it has already resolved an object still in scope (although I am guessing that it may think its out of scope since ASP.Net abandoned the scope upon await).
For any interested, I am going to try and post about this on my blog soon (see my user page if actually interested, not spamming SO myself).

How can I use Rhino mocks to mock just one value in a test object?

Been making some changes to our code, and now I need to re-factor some unit tests to make sure they're compatible with the new code. I've come up against a problem. In this:
ChannelLoad loader = new ChannelLoad(_customerDbMock, _bulkCopyMock);
loader.Execute(taskId);
The "loader" object is now trying to connect to another object in order to get a string value whereas before the string was returned automatically. So the obvious solution is to mock that object to return a suitable value for the test. However for various reasons I can't easily do this.
Ideally what I'd like to be able to do is to get a "real" (i.e as specified in code) loader object that performs a "real" Execute method but which has a "mock" value for that particular string. But I'm really not sure how to do this - even if it's possible - with Rhino Mocks. The string property in question isn't abstract or anything - it's protected and it's actually read-only. This is how it looks inside "loader":
protected string DbConnectionString
{
get
{
return _Service.GetLocalDatabase().GetConnectionString(_Service);
}
}
And the problem is that for the test environment "GetLocalDatabase" returns nothing.
Anyone help me out here? Is there a way I can mock this up using Rhino Mocks or is my only option to refactor the code to make it not rely on an external object? If the latter, pointers would also be helpful.
Cheers,
Matt
Two other options if you don't want to inject _Service:
Create a class that inherits from ChannelLoad (call it "TestableChannelLoader" or something) and
overwrite the DbConnectionString-Property or
extract a method "GetConnectionString" that you can override in your new class and call it in the DbConnectionString-Property
I see that loader has dependency to _Service. So, you need to inject mock of this dependency to loader in order to change DbConnectionString property behavior.

Is HttpContextWrapper all that....useful?

I've been going through the process of cleaning up our controller code to make each action as testable. Generally speaking, this hasn't been too difficult--where we have opportunity to use a fixed object, like say FormsAuthentication, we generally introduce some form of wrapper as appropriate and be on our merry way.
For reasons not particularly germaine to this conversation, when it came to dealing with usage of HttpContext, we decided to use the newly created HttpContextWrapper class rather than inventing something homegrown. One thing we did introduce was the ability to swap in a HttpContextWrapper (like say, for unit testing). This was wholly inspired by the way Oren Eini handles unit testing with DateTimes (see article, a pattern we also use)
public static class FooHttpContext
{
public static Func<HttpContextWrapper> Current = ()
=> new HttpContextWrapper(HttpContext.Current);
public static void Reset()
{
Current = () => new HttpContextWrapper(HttpContext.Current);
}
}
Nothing particularly fancy. And it works just fine in our controller code. The kicker came when we go to write unit tests. We're using Moq as our mocking framework, but alas
var context = new Mock<HttpContextWrapper>()
breaks since HttpContextWrapper doesn't have a parameterless ctor. And what does it take as a ctor parameter? A HttpContext object. So I find myself in a catch 22.
I'm using the prescribed way to decouple HttpContext--but I can't mock a value in because the original HttpContext object was sealed and therefore difficult to test. I can map HttpContextBase, which both derive from--but that doesn't really get me what I'm after. Am I just missing the point somewhere with regard to HttpContextWrapper?
Edit to clarify intent
We found ways to solve the problem--but I guess the ultimate question we're walking away with is what value HttpContextWrapper brings to the table? I don't doubt somewhere someone totally had an a-ha! moment with it, but it just doesn't come to me. Most postings I see here discuss it in terms of testability--but my own experience has led me to believe that it didn't bring much in that context. Unless we're doing it wrong. (Wholly possible).
This blog post explains it pretty well:
http://splinter.com.au/httpcontext-vs-httpcontextbase-vs-httpcontext
The point is that 'vintage' HttpContext does not implement HttpContextBase, and isn't virtual, and therefore cannot be Mocked. HttpContextBase was introduced in 3.5 as a mockable alternative. But there's still the problem that vintage HttpContext doesn't implement HttpContextBase.
So HttpContextWrapper is a handy wrapper class (or 'kludge') that does implement HttpContextBase, and can be used when injecting a 'real' HttpContext using IOC, usually with a factory method like this: () => new HttpContextWrapper(HttpContext.Current)
You should be using the abstract HttpContextBase which is much easier to mock instead of HttpContextWrapper.
public static Func<HttpContextBase> Current =
() => new HttpContextWrapper(HttpContext.Current);
And in your unit test:
SomeClass.Current = MockHttpContextBase(); // Sorry I don't know the syntax for Moq
One real world example other than testing.
Besides mocking I stumbled upon a peculiar issue that the wrapper class really helped me solve. We have an application in Azure and we have control only on the application. It sits behind a reverse proxy which changes the host header of the incoming requests and sends the original host in a custom header. The application relies on the host header in order to build dynamic links, validate redirects etc. so we needed a way to substitute the host that was set in the HttpContext.HttpRequests.Url property. Since we exposed the HttpContext only as HttpContextBaase using the wrapper everywhere in the app we were able to create a class that inherits HttpContextWrapper and overrides the Request and then returns object that inherits from the RequestWrapper and overrides the Url property. So in the end the application replaced the host in the url that ASP.NET used for the context with the custom host from the custom header the reverse proxy has set. There was no other way from within the app to do that other than manually searching through the code where HttpContext.Request.Url is used and applying fix.

Categories

Resources