To answer your question, you need the following in your test:
var requestBase = new Mock<HttpRequestBase>();
requestBase.Setup(r => r.ServerVariables)
.Returns(new NameValueCollection { {"HTTP_X_REWRITE_URL", "your url"} });
var httpContext = new Mock<HttpContextBase>();
httpContext.Setup(x => x.Request).Returns(requestBase.Object);
var ctrCtx = new Mock<ControllerContext>();
ctrCtx.Setup(x => x.HttpContext).Returns(httpContext.Object);
demoController.ControllerContext = ctrCtx.Object;
However as @Mark suggested you don't need to create concrete instance of DeviceDetection
inside your action, you need to inject it. But instead of injecting a concrete instance, it is better to wrap it into interface IDeviceDetector
and inject this abstraction.
I will give a number of advantages:
- Your action does not depend on the implementation of
DeviceDetection
Mock<IDeviceDetection>
allows you to raise exception on setup, to test exception handling of your try-catch
block.
- You can assert that
DetectDevice()
method is called
Another suggestion - never use try{} catch(Exception ex){}
, you should catch only those exceptions which you can handle. As you don't know which type of exception can be thrown and how to handle it effectively, e.g. it can be OutOfMemoryException
. This article can give you basic ideas of different ways to handle exception in MVC.
UPDATE: As I see you are using Unity as IoC container. Unity has a possibility to inject constructor parameters. So again you need to extract an interface from DeviceDetector
let's say IDeviceDetector
. Register it
container.RegisterType<IDeviceDetector, DeviceDetector>(new InjectionConstructor(
HttpContext.Current.Request.ServerVariables["HTTP_X_REWRITE_URL"].ToString()));
Register DeviceDetector
with TransientLifetimeManager
.
Then your controller should look like
public class DemoController : Controller
{
private readonly ICommonOperationsRepository _commonRepo;
private readonly IDeviceDetection _deviceDetection;
public DemoController (
ICommonOperationsRepository commonRepo,
IDeviceDetection deviceDetection)
{
_commonRepo = commonRepo;
_deviceDetection = deviceDetection;
}
public ActionResult Default()
{
var model = new DemoModel();
_deviceDetection.DetectDevice();
model.ListTopListing.AddRange(_commonRepo.GetListings());
return View(model);
}
}
Note, in this case you need to write unit tests for your Unity container to verify that your injections are resolved correctly. Your unit test may look like:
[TestMethod]
public void Test()
{
var repository = new Mock<ICommonOperationsRepository>();
var deviceDetection = new Mock<IDeviceDetection>();
var controller = new DemoController(repository.Object, deviceDetection.Object);
controller.Default();
deviceDetection.Verify(x => x.DetectDevice(), Times.Once());
}