var mockedService = new Mock<IService>();
mockedService.Setup(x => x.InterfaceMethod(args)).Returns(value);
_Service = mockedService.Object;
MyController controller =new MyController(_Service);
var result = (ViewResult)controller.Foo();
Now this Foo() Method contains the Following API Call
HttpContext.GetGlobalResourceObject(...,..);
But the HTTPContext is null, as i'm just unit testing , i have not Authenticated. and hence not populated the HTTPContext Object.
I cant set expectations on this class because the HTTPContext is sealed.
I've been searching in the net , but there were only samples to fake the HTTPContextBase
Now how do i get my Unit Test to Pass. Any Suggestions.?
thanks ,
vijay
The problem is you are not setting up an expectation for the "Centres" method. When you mock an object all implementations are replaced with a Noop until you specify otherwise using an Expectation.
I'm guessing you mocked GetValueFromResource rather than Centres because Centres calls GetValueFromResource. If this is the case, mocking GetValueFromResource is likely a superfluous fake and you don't need it.
Also, as has been pointed out on several other Moq posts, you'll need to make sure that you are not mocking what you are testing. If you are actually trying to test MyController, you'd want to mock any dependencies it has, but not MyController itself. This will cause you no end of confusion.
Edit
Based on this feedback it seems you have learned that your true problem is that you need to mock HTTPContext. Mocking HTTPContext is nontrivial. There are a few tools that can do it natively, like Type Mock, but the problem is that ambient context is not testable.
What you should be doing is requesting dependencies that give you the information you need while abstracting away their implementation. For example, in your case it seems like you are using HTTPContext to access resources. If you need something like this a good interface you could use would be:
public interface IResourceStore
{
object GetGlobalResource(string classKey, string resourceKey);
}
Your default implementation would use HTTPContext, but now you have an interface you can mock and have your MyController class use, rather than HTTPContext directly.
Mock<IResourceStore> resourceStore = new Mock<IResourceStore>();
//setup resourceStore expectations here
MyController testingTarget = new MyController(_Service, resourceStore.Object);
//target assertions here
Hope this helps.
Related
I have my normal Entity Framework context, which is like this:
public class LikvidoWebsitesApiContext : IdentityDbContext<ApplicationUser>, ILikvidoWebsitesApiContext
{
// code
}
I have made an interface, which has my DBSets.
In my normal solution, I set it up in Ninject like this:
kernel.Bind<ILikvidoWebsitesApiContext>().To<LikvidoWebsitesApiContext>().InRequestScope();
I use the context in my services by adding the ILikvidoWebsitesApiContext inside the constructor, and then I can use the database.
My question is: how do I set this up in the unit Test?
I have tried to do the following:
kernel.Bind(typeof(ILikvidoWebsitesApiContext))
.To(typeof(Mock<LikvidoWebsitesApiContext>))
.Register(true);
(Using the Moq framework)
However, this gives the:
System.InvalidCastException: 'Unable to cast object of type 'Moq.Mock`1[Likvido.Domain.Services.Data.LikvidoWebsitesApiContext]' to type 'Likvido.Domain.Services.Data.ILikvidoWebsitesApiContext'.'
Which do make sense, but I am very unsure how to fix it?
After a quick look at the Ninject wiki I came across
Providers, Factory Methods and the Activation Context
Where they show how to use a Provider to build up instances.
Following the suggestion in the wiki it was advised to extend Provider<T> which includes strong typing.
public MoqContextProvider : Provider<ILikvidoWebsitesApiContext> {
protected override ILikvidoWebsitesApiContext CreateInstance(IContext context) {
var mock = new Mock<ILikvidoWebsitesApiContext>();
// Set up of mock members
return mock.Object;
}
}
And then it is just a matter of plugging into the container
kernel.Bind<ILikvidoWebsitesApiContext>().ToProvider(new MoqContextProvider());
There was also a suggestion about using Factory Methods
A lighter weight alternative to writing IProvider implementations is to bind a service to a delegate method.
kernal.Bind<ILikvidoWebsitesApiContext>()
.ToMethod(context => {
var mock = new Mock<ILikvidoWebsitesApiContext>();
// Set up of mock members
return mock.Object;
});
The provided Func will be bound to the service type for deferred binding and called later when a new instance of the service (i.e. ILikvidoWebsitesApiContext) is required.
Remember that when using Moq you need to set up the desired behavior of the mocks.
I've seen lots of code samples using an IoC Container with registrations such as:
// Autofac
builder.Register(c => new HttpContextWrapper(HttpContext.Current))
.As<HttpContextBase>()
.InstancePerRequest();
// Again Autofac
builder.RegisterModule(new AutofacWebTypesModule());
(see src for AutofacWebTypesModule HERE )
// Castle Windsor
container.Register(Component.For<HttpContextBase()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current)));
Together with controllers using contructor injection:
public class HomeController : Controller
{
private readonly HttpContextBase _httpContext;
public HomeController(HttpContextBase httpContext)
{
_httpContext = httpContext;
}
//....
}
Question 1:
Can you please explain the reason of wrapping HttpContextBase,HttpRequestBase and so on..?
Question 2:
What would be the difference between the Injected HttpContextBase vs HttpContext (Controller's property) vs System.Web.HttpContext.Current
Update
Question 3:
Which HttpContext to use in code, the Injected One or it is also good to call it through HttpContext and System.Web.HttpContext.Current? Are there any issues if calling both ways?
Answer 1
HttpContext is a notorious pain when it comes to testing, since it only exists in the context of a request. Since .net 3.5 HttpContextBase is an abstraction of HttpContext and lends itself to being injected through IOC frameworks
By letting the IOC container handle it you can register a different/deterministic instance be injected into your components at test time. In normal code you would inject the HttpContextWrapper that is the default implementation
From the linked page:
The HttpContextBase class is an abstract class that contains the same
members as the HttpContext class. The HttpContextBase class enables
you to create derived classes that are like the HttpContext class, but
that you can customize and that work outside the ASP.NET pipeline.
When you perform unit testing, you typically use a derived class to
implement members with customized behavior that fulfills the scenario
you are testing.
Answer 2
The injected HttpContextBase would return data that is needed in order for the test to succeed: a specific query string, a specific query, etc. Usually the injected implementation would only contain the needed methods for the test, ignoring all others, e.g the context .User.Identity.Name property in order to test authentication.
Answer 3
In code, you must always use the HttpContextBase that is injected, since you don't want to depend on a concrete implementation that may fail at test time. If calling both ways you may encounter problems, most notably in tests since the HttpContext.Current will return null.
I have a class that inherits from System.Web.Mvc.RedirectResult which overrides ExecuteResult. How do I unit test this?
Thanks.
Depends on what you override does.
In general, mock HttpContextBase, create the necessary RouteData and use those two elements to create a ControllerContext.
Instantiate your custom RedirectResult, call ExecuteResult passing in your previously created ControllerContext and then make assertions on the various bits and pieces that you mocked.
If you want a more comprehensive answer, I would need more details as to exactly what your override does.
Both have Request and Response properties, but I can't write a method that takes either HttpContext or HttpContextBase. In some places either one or the other is available so I need to handle both. I know HttpContextWrapper can convert in one direction, but still... why is it like this?
HttpContext has been around since .NET 1.0. Because of backward compatibility reasons, they can't change that class. HttpContextBase was introduced in ASP.NET MVC to allow for better testability because it makes it easier to mock/stub it.
This is an old question but I just had the same problem and the answer is in Gunder's comment.
Create you methods to use HttpContectBase and then wrap your context in a HttpContextWrapper when you want to call it from your code
public class SomeClass{
... other stuff in your class
public void MyMethod(HttpContextBase contextbase){
...all your other code
}
}
Usage
var objSomeClass = new SomeClass();
objSomeClass.MyMethod(new HttpContextWrapper(HttpContext.Current));
I think HttpContext.Current will be null if you make this call via ajax, I will investigate how to get the context and update this post.
Currently I have an ActionFilter that gets the current users name from HttpContext and passes it into the action which uses it on a service method. eg:
Service.DoSomething(userName);
I now have a reason to do this not at the action level but the controller constructor level. Currently I'm using structure map to create controllers and inject the service. I'm looking at something like:
public interface IUserProvider
{
string UserName { get; }
}
public class HttpContextUserProvider : IUserProvider
{
private HttpContext context;
public HttpContextUserProvider(HttpContext context)
{
this.context = context;
}
public string UserName
{
get
{
return context.User.Identity.Name;
}
}
}
That said, my IoC foo is really weak as this is the first project I've used it on.
So my question is... how can I tell structure map to pass in HttpContext in the constructor for HttpContextUserProvider? This just seems weird... I'm not sure how to think of HttpContext.
It sounds like you should be using HttpContextBase instead of HttpContextUserProvider. This is a out-of-box abstraction of HttpContext and allows you to create a mock, write UnitTests and inject your dependencies.
public class SomethingWithDependenciesOnContext
{
public SomethingWithDependenciesOnContext(HttpContextBase context) {
...
}
public string UserName
{
get {return context.User.Identity.Name;}
}
}
ObjectFactory.Initialize(x =>
x.For<HttpContextBase>()
.HybridHttpOrThreadLocalScoped()
.Use(() => new HttpContextWrapper(HttpContext.Current));
Have an interface abstract HttpContext.Current. Expose only the methods you need. GetUserName() would call HttpContext.Current.User.Identity.Name in the implementation, for example. Make that as thin as possible.
Take that abstraction and inject it into your other provider class. This will allow you to test the provider by mocking the http context abstraction. As a side benefit, you can do other nifty things with that HttpContext abstraction besides mock it. Reuse it, for one thing. Add generic type params to bags, etc.
I'm not sure why you're bothering. It seems like just using HttpContext.Current directly in HttpContextUserProvider is the right thing to do. You're never going to be substituting in a different HttpContext...
Maybe I left something out, but the above answer doesn't work for me (has since been deleted -- it was still a useful answer though -- it showed how to tell SM to pass constructor arguments). Instead if I do:
ObjectFactory.Initialize(x =>
{
x.BuildInstancesOf<HttpContext>()
.TheDefault.Is.ConstructedBy(() => HttpContext.Current);
x.ForRequestedType<IUserProvider>()
.TheDefault.Is.OfConcreteType<HttpContextUserProvider>();
});
I get it to work. I did this after finding: If you need something in StructureMap, but you can’t build it with new()…
Edit:
Thanks to Brad's answer I think I have a better handle on HttpContext. His answer definitely works, I just am not sure I like having the call to HttpContext.Current inside a class (it seems like it hides the dependency, but I'm far from an expert on this stuff).
The above code should work for injecting HttpContext as far as I can tell. Matt Hinze brings up the added that point that if all I need from HttpContext is the User.Identity.Name, my design should be explicit about that (having an Interface around HttpContext only exposing what I need). I think this is a good idea.
The thing is over lunch I kinda realized my service really only needs to depend on a string: userName. Having it depend on IUserProvider might not have much added value. So I know I don't want it to depend on HttpContext, and I do know all I need is a string (userName) -- I need to see if I can learn enough StructureMap foo to have make this connection for me. (sirrocoo's answer gives a hint on where to start but he deleted it :*( ).