I\'m building an ASP.NET MVC4 app. I\'m not using any mocking framework and, if possible, would prefer not to at this point. My question is 2 parts.
I have a controll
Is this a best-practice for application wide variable usage?
Best practice is a bit of a subjective notion and without fully explaining your scenario and what precisely are you trying to achieve I prefer not to discuss it.
We cannot discuss whether this is best practice but from what I can see it is not wrong either. It is not wrong because you are using the abstractions allowing the code to be unit tested.
In the unit test, how can I add the application level variables the controller needs?
You could use a mocking framework such as Rhino Mocks to mock the abstractions that the controller needs. Let's take as an example the following controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var myVar = (MyVar)HttpContext.Application["MyVar"];
return Content(myVar.Foo);
}
}
and we would like to unit test the Index action. Here's a sample unit test:
[TestMethod]
public void Index_Action_Should_Retrieve_MyVal_From_AppState()
{
// arrange
var target = new HomeController();
var httpContext = MockRepository.GeneratePartialMock<HttpContextBase>();
var application = MockRepository.GeneratePartialMock<HttpApplicationStateBase>();
application.Expect(x => x["MyVar"]).Return(new MyVar { Foo = "bar" });
httpContext.Expect(x => x.Application).Return(application);
target.ControllerContext = new ControllerContext(httpContext, new RouteData(), target);
// act
var actual = target.Index() as ContentResult;
// assert
Assert.AreEqual("bar", actual.Content);
}
In general globals aren't good for testing. There are at least two approaches you could take.
Use a mocking framework like Pex/Moles, NMock, etc.
Use an inversion-of-control approach (NInject is my favorite). If class like a controller has an external dependency, it asks for the interface, typically in its constructor.
private readonly IApplicationSettings _settings;
public MyController(IApplicationSettings settings) { _settings = settings; }
void someMethod() { _settings.Get("MyVar"); }
This way you can write real and test implementations.
public LiveAppSettings : IApplicationSettings
{
public string Get(string key)
{
return HttpContext.Current.Application[key];
}
}
With Ninject, you can bind either implementation at application startup:
var kernel = new StandardKernel();
kernel.Bind<IApplicationSettings>().To<LiveAppSettings>();