"Inject" Request.Url.Hosts - ASP.net MVC - asp.net-mvc

In my ASP.net MVC application i need to get the host of the application because I have to distinguish between multiple domains/instances.
In consideration of a good design and testability I do not want to get it like this:
public ViewResult Show(int id)
{
string host = Request.Url.Host;
....
}
Is there a possibility to "inject" it through the constructor.
What would be the cleanest solution for this problem?

You could also use some constructors for your controller like so :
public MyController() : this(DefaultHostGetter) { }
public MyController(Func<string> hostGetter)
{
this.hostGetter = hostGetter;
}
private string DefaultHostGetter() { return this.Request.Url.Host; }
the view action would be :
public ViewResult Show(int id)
{
string host = this.hostGetter();
....
}
you would then be able to test your controller by supplying a different host getter (a mock).

Maybe you don't need "injection" in this case. I think for good testability the cleanest solution will be mocking of your Request. Example (using Moq library):
var request = new Mock<HttpRequestBase>();
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/any"));
var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);
var controller = new YourController();
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);

Related

IdependencyResolver is always null in unit test using moq

I've implemented ninject in a mvc project and this works as expected now I'm wanting to unit test, but can't seem to get it to work:
controller:
private IDependencyResolver _resolver;
public HomeController(IDependencyResolver resolver)
{
_resolver = resolver;
}
public ActionResult Index()
{
var model = _resolver.GetService<ISignUpViewModel>();
return PartialView("Login", model);
}
Unit Test
private IDependencyResolver _resolverMock;
[TestMethod]
public void SignUpTest()
{
var ctrl = new HomeController(_resolverMock);
var signUpMock = new Mock<ISignUpViewModel>();
ctrl.Index();
ctrl.ViewData.Model = signUpMock;
//Assert.AreEqual("", "");
}
The resolver is always null.
Ive looked at Ninject.MockingKernel.Moq should I set the resolver in there?
Any idea where I'm going wrong?
Thanks
In the unit test you manually create HomeController instance, So you need mock IDependencyResolver. For example:
var resolverMock = new Mock<IDependencyResolver>();
var ctrl = new HomeController(resolverMock.Object);
....

NUnit - UpdateModel issue: NullReferenceException

I have problem with testing classes, which using UpdateModel() method.
I get System.NullReferenceException.
I use NUnit.
This is my method from HomeController:
public ActionResult ProjectsEdit(Projects model)
{
var projects = db.Projects.First();
projects.Content = model.Content;
UpdateModel(projects);
db.SaveChanges();
return RedirectToAction("Projects");
}
Here is test class:
[Test]
public void ProjectsEditPostTest()
{
var routeData = new RouteData();
var httpContext = MockRepository.GenerateStub<HttpContextBase>();
//var httpContext = new FakeHttpContext("Edit");
FormCollection formParameters = new FormCollection();
ControllerContext controllerContext =
MockRepository.GenerateStub<ControllerContext>(httpContext,
routeData,
controller);
controller.ControllerContext = controllerContext;
// Act
string newContent = "new content";
Projects projects = new Projects { ID = 1, Content = newContent };
controller.ProjectsEdit(projects);
// Assert
Assert.AreEqual(newContent, controller.db.Projects.First().Content);
}
What should I do to make it works?
Just add the following line in the Assert phase:
controller.ValueProvider = formParameters.ToValueProvider();
It assigns a value provider to the controller on which the UpdateModel method relies. This value provider is associated to the FormCollection variable you have defined and which allows you to pass some values.
You may also check a similar answer which uses MvcContrib.TestHelper to simplify the Arrange phase.

how to add session to mock httpcontext?

As per scott hanselman's mock example http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx I tried to mock httpcontext using MockHelpers as code snippet below
controller = GetAccountController();
ActionResult result = controller.ChangePassword();
HttpContextBase hb = MvcMockHelpers.FakeHttpContext("~/Account/ChangePassword");
hb.Session.Add("id", 5);
// Assert Assert.AreEqual(5, (int)hb.Session["id"]);
I noticed that the session wasn't added and didn't receive any error either. The session object's properties had below value
Count = 0, CodePage = 0, Content = null, IsCookieLess = null, IsNewSession = null, IsReadOnly = null, IsSynchronized = null, Keys = null, LCID = 0, Mode = off, SessionId = null, Static Objects = null, SynRoot = null, TimeOut = 0
I was getting same result for Rhino mock and Moq.
Please advice me how to add session to mock httpcontext.
Thanks in advance.
Here's what I use to mock not only the session, but most other objects that you will need (request, response, etc), this code is a collection of code of Steve Sanderson and others as well as my own, note that the session is faked using a dictionary
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using System.Web.Routing;
using System.Web.Mvc;
namespace ECWeb2.UnitTests {
public class ContextMocks {
public Moq.Mock<HttpContextBase> HttpContext { get; private set; }
public Moq.Mock<HttpRequestBase> Request { get; private set; }
public Moq.Mock<HttpResponseBase> Response { get; private set; }
public RouteData RouteData { get; private set; }
public ContextMocks(Controller onController) {
// Define all the common context objects, plus relationships between them
HttpContext = new Moq.Mock<HttpContextBase>();
Request = new Moq.Mock<HttpRequestBase>();
Response = new Moq.Mock<HttpResponseBase>();
HttpContext.Setup(x => x.Request).Returns(Request.Object);
HttpContext.Setup(x => x.Response).Returns(Response.Object);
HttpContext.Setup(x => x.Session).Returns(new FakeSessionState());
Request.Setup(x => x.Cookies).Returns(new HttpCookieCollection());
Response.Setup(x => x.Cookies).Returns(new HttpCookieCollection());
Request.Setup(x => x.QueryString).Returns(new NameValueCollection());
Request.Setup(x => x.Form).Returns(new NameValueCollection());
// Apply the mock context to the supplied controller instance
RequestContext rc = new RequestContext(HttpContext.Object, new RouteData());
onController.ControllerContext = new ControllerContext(rc, onController);
onController.Url = new UrlHelper(rc);
}
ContextMocks() {
}
// Use a fake HttpSessionStateBase, because it's hard to mock it with Moq
private class FakeSessionState : HttpSessionStateBase {
Dictionary<string, object> items = new Dictionary<string, object>();
public override object this[string name] {
get { return items.ContainsKey(name) ? items[name] : null; }
set { items[name] = value; }
}
}
}
}
The code you referenced explains how you can fake out the httpcontext - it doesn't actually do anything when you call "hb.Session.Add" - it just stops the test from failing because of a dependency on the HttpContext.
You can use the MVC Contrib library provided by the Outercurve Foundation to mock session state and other objects that are available during the handling of a normal request (HttpRequest, HttpResponse...etc.).
http://mvccontrib.codeplex.com/ (or use NuGet to download it)
It contains a TestHelper library which helps you to quickly create unit tests.
For example:
[TestMethod]
public void TestSomething()
{
TestControllerBuilder builder = new TestControllerBuilder();
// Arrange
HomeController controller = new HomeController();
builder.InitializeController(controller);
// Act
ViewResult result = controller.About() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
Using the TestControllerBuilder type provided by the MVC Contrib TestHelper library you can quickly initialize your controller and initialize its internal data members (HttpContext, HttpSession, TempData...).
Of course, the HttpSessionState itself is also mocked this way, so adding something to it (Session.Add) won't actually do something. As is intended, we mocked it.
Seems like you want to mock the HttpContext, but still have it setup with a working session state. Sounds like you want to do something as described here:
http://jasonbock.net/jb/Default.aspx?blog=entry.161daabc728842aca6f329d87c81cfcb
This is what i usually do
//Mock The Sesssion
_session = MockRepository.GenerateStrictMock<httpsessionstatebase>();
_session.Stub(s => s["Connectionstring"]).Return(Connectionstring);
//Mock The Context
_context = MockRepository.GenerateStrictMock<httpcontextbase>();
_context.Stub(c => c.Session).Return(_session);
var databaseExplorerController = new DatabaseExplorerController(repository);
//Assign COntext to controller
databaseExplorerController.ControllerContext = new ControllerContext(_context, new RouteData(),
_databaseExplorer);
I've written a small aricle about this at
http://www.gigawebsolution.com/Posts/Details/66/Mock-Session-in-MVC3-using-Rhino-Mock
Hope this helps
A little bit late, but this is what is use.
I''m using the MoQ framework from https://code.google.com/p/moq/
Now the session is usable in the controller implementation.
private class MockHttpSession : HttpSessionStateBase
{
readonly Dictionary<string, object> _sessionDictionary = new Dictionary<string, object>();
public override object this[string name]
{
get
{
object obj = null;
_sessionDictionary.TryGetValue(name, out obj);
return obj;
}
set { _sessionDictionary[name] = value; }
}
}
private ControllerContext CreateMockedControllerContext()
{
var session = new MockHttpSession();
var controllerContext = new Mock<ControllerContext>();
controllerContext.Setup(m => m.HttpContext.Session).Returns(session);
return controllerContext.Object;
}
[TestMethod]
public void Index()
{
// Arrange
MyController controller = new MyController();
controller.ControllerContext = CreateMockedControllerContext();
// Act
ViewResult result = controller.Index() as ViewResult;
....
}

ASP.NET MVC Unit Testing with Repository Pattern

I am trying to get my feet wet with asp.net mvc3 and unit testing.
I have created a model which uses the repository pattern. Here's the interface:
public interface IExtensionRepository
{
IList<Extensions> ListAll();
}
Here's the repository:
public class ExtensionRepository : IExtensionRepository
{
private ExtensionsLSDataContext _dataContext;
public ExtensionRepository()
{
_dataContext = new ExtensionsLSDataContext();
}
public IList<Extensions> ListAll()
{
var extensions = from ext in _dataContext.Extensions
select ext;
return extensions.ToList();
}
}
Here's the controller:
public class ExtensionController : Controller
{
private IExtensionRepository _repository;
public ExtensionController()
: this(new ExtensionRepository())
{
}
public ExtensionController(IExtensionRepository repository)
{
_repository = repository;
}
}
The pages seem to function as designed. Things go astray with my unit test, however. It resides in another project in the same solution. I am using Moq and NUnit. Here's my test:
[Test]
public void Test_Extension_Index_Views()
{
Mock<Extensions> extension = new Mock<Extensions>();
List<Extensions> extList = new List<Extensions>();
extension.Object.Extension = "5307";
extension.Object.Extension_ID = 1;
extension.Object.ExtensionGroup_ID = 1;
extList.Add(extension.Object);
Mock<IExtensionRepository> repos = new Mock<IExtensionRepository>();
repos.Setup(er => er.ListAll()).Returns(extList);
var controller = new ExtensionController(repos);
var result = controller.Index() as ViewResult;
Assert.AreEqual("Index", result.ViewName);
}
I am getting the following errors for the line that begins "var controller...":
The best overloaded method match for
'MvcApplication1.Controllers.ExtensionController.ExtensionController(MvcApplication1.Models.IExtensionRepository)'
has some invalid arguments
And:
Argument 1: cannot convert from
'Moq.Mock'
to
'MvcApplication1.Models.IExtensionRepository'
I know I've missed the boat somewhere, but I haven't a clue as to where... any ideas?
Change this:
var controller = new ExtensionController(repos);
to this:
var controller = new ExtensionController(repos.Object);
PS.: I know it sucks, but that's the way Moq was designed.

How to mock Request.Files[] in MVC unit test class?

I want to test a controller method in MVC unit test.
For my controller method to test, I require a Request.Files[] collection with length one.
I want to mock Request.Files[] as I have used a file upload control on my view rendered by controller method.
Can anyone please suggest how can I mock request.file collection in my unit test.
thanks,
kapil
You didn't mention what mocking framework you are using but here's how you would do it with Rhino Mocks:
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(Request.Files.Count);
}
}
Unit test:
[TestMethod]
public void SomeTest()
{
// arrange
var controller = new HomeController();
var context = MockRepository.GenerateStub<HttpContextBase>();
var request = MockRepository.GenerateStub<HttpRequestBase>();
var files = MockRepository.GenerateStub<HttpFileCollectionBase>();
context.Stub(x => x.Request).Return(request);
files.Stub(x => x.Count).Return(5);
request.Stub(x => x.Files).Return(files);
controller.ControllerContext = new ControllerContext(context, new RouteData(), controller);
// act
var actual = controller.Index();
// assert
Assert.IsInstanceOfType(actual, typeof(ViewResult));
var viewResult = actual as ViewResult;
Assert.IsInstanceOfType(viewResult.ViewData.Model, typeof(int));
Assert.AreEqual(5, viewResult.ViewData.Model);
}
Remark: Using MVCContrib.TestHelper this test could be greatly simplified especially the context mocking part and the asserts as well:
[TestMethod]
public void SomeTest()
{
// arrange
var sut = new HomeController();
InitializeController(sut);
Files["test.txt"] = MockRepository.GenerateStub<HttpPostedFileBase>();
// act
var actual = sut.Index();
// assert
actual
.AssertViewRendered()
.WithViewData<int>()
.ShouldBe(1);
}
Scott Hanselman has a blog post covering this using Moq.

Resources