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.
Related
Inside controller I have view which returns simple object to the view.
public ActionResult SomeAction(int?id)
{
MyModel model = new MyModel();
return View(model);
}
how can I unit test this controller in order to check ViewResult,
basically to
check if view is initialized? Basically how can I mock this MyModel
inside my unit test?
[Test]
public void Can_Open_SomeAction()
{
// controller is already set inside `SetUp` unit step.
ViewResult res = this.controller.SomeAction() as ViewResult;
Assert.IsNotNull(res);
}
Update:
public ActionResult SomeAction(int?id)
{
MyModel model = new MyModel();
this.PopulatePageCombos(id);
return View(model);
}
The way you set this up, I presume you simply want to see if the model is not null:
[Test]
public void Can_Open_SomeAction()
{
ViewResult res = this.controller.SomeAction() as ViewResult;
Assert.IsNotNull(res);
var model = result.Model as MyModel;
Assert.IsNotNull(model);
}
Mocking would only make sense in a context where you'd get that model from an underlying interface, for example if you had:
public ActionResult SomeAction(int?id)
{
MyModel model = _myModelQuerier.Fetch(id.Value);
return View(model);
}
then you could get around something like
var modelQuerierMock = MockRepository.GenerateMock<IMyModelQuerier>();
modelQuerierMock.Stub(x => x.Fetch(Arg<int>.Is.Anything)).Return(new MyModel(2, "product"));
inside your test class
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);
....
I have a controller in which I am unit testing my Index action. I am having problem in unit testing User.Identity.GetUserId()
This is my controller
public ActionResult Index()
{
string userId = User.Identity.GetUserId();
DemoModel demoModel = _demoModelService.GetByUserId(userId);
MyModel myModel = new MyModel()
{
Name = demoModel.Name;
Description = demoModel.Description;
}
return View(myModel);
}
This is my Unit Test:
public void Test_Index_Action()
{
//Act
var result = controller.Index() as ViewResult;
//Assert
Assert.AreEqual("", result.ViewName);
}
When I debug my test method, as it reaches the first line of code(User.Identity.GetUserId) of my Index action, it generates null UserId. How can I access the userId in unit testing this code?
I've been struggeling with mvc unit test my self, while there are known techniques to improve testability of your mvc application, most of the projects I worked on are sadly not following them.
So I decided to start this project to help me and others who love to unit test their mvc application. Please take a look at: https://github.com/ibrahimbensalah/Xania.AspNet.Simulator.
Here is an example unit test class
using System.Web.Mvc;
using NUnit.Framework;
using Xania.AspNet.Simulator;
public class SimulatorTests
{
[Test]
public void ActionExecuteTest()
{
// arange
var controller = new TestController();
// act
var result = controller.Execute(c => c.Index());
// assert
Assert.AreEqual("Hello Simulator!", result.ViewBag.Title);
}
[Test]
public void UnAuthorizedActionTest()
{
// arrange
var controller = new TestController();
// act
var result = controller.Execute(c => c.UserProfile());
// assert
Assert.IsInstanceOf<HttpUnauthorizedResult>(result.ActionResult);
}
[Test]
public void AuthorizedActionTest()
{
// arrange
var controller = new TestController();
// act
var result = controller.Action(c => c.UserProfile()).Authenticate("user", null).Execute();
// assert
Assert.IsInstanceOf<ViewResult>(result.ActionResult);
}
}
public class TestController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Hello Simulator!";
return View();
}
[Authorize]
public ActionResult UserProfile()
{
return View();
}
}
There is a simple controller that a querystring is read in constructor of it.
public class ProductController : Controller
{
parivate string productName;
public ProductController()
{
productName = Request.QueryString["productname"];
}
public ActionResult Index()
{
ViewData["Message"] = productName;
return View();
}
}
Also I have a function in unit test that create an instance of this Controller and I fill the querystring by a Mock object like below.
[TestClass]
public class ProductControllerTest
{
[TestMethod]
public void test()
{
// Arrange
var querystring = new System.Collections.Specialized.NameValueCollection { { "productname", "sampleproduct"} };
var mock = new Mock<ControllerContext>();
mock.SetupGet(p => p.HttpContext.Request.QueryString).Returns(querystring);
var controller = new ProductController();
controller.ControllerContext = mock.Object;
// Act
var result = controller.Index() as ViewResult;
// Assert
Assert.AreEqual("Index", result.ViewName);
}
}
Unfortunately Request.QueryString["productname"] is null in constructor of ProductController when I run test unit.
Is ther any way to fill a querystrin by a mocking and get it in constructor of a control?
There is a simple controller that a querystring is read in constructor of it.
You shouldn't be doing this and such controller shouldn't exist. The controller context is not yet initialized in the constructor and it will fail not only for the unit test but in real.
You should use the Initialize method where you have access to the request context.
i've got the following Action Method I'm trying to moq test. Notice the AcceptVerbs? I need to make sure i'm testing that.
here's the method.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Include = "Subject, Content")]Post post,
HttpPostedFileBase imageFileName)
{
...
}
here's the moq code i have...
[TestMethod]
public void Create_Action_snip_sniop_When_Http_Post_Is_Succesful()
{
// Arrange.
var mock = new Mock<ControllerContext>();
mock.SetupGet(m => m.HttpContext.Request.HttpMethod).Returns("POST");
// Snip some other arrangements.
var controller = PostController;
controller.ControllerContext = mock.Object;
// Act.
var viewResult = controller.Create(post, image.Object) as ViewResult;
// Assert.
Assert.IsNotNull(viewResult);
// TODO: Test that the request was an Http-Post.
what do i need to do to verify the request was a post?
Your attribute won't be invoked when running as a unit test because it is normally invoked by the ControllerActionInvoker as part of the Mvc "stack". What I've done in cases like this is to write a test to make sure that the correct attribute is applied to the action with the correct parameters. Then I trust that the framework will do its job correctly.
Doing this requires reflection:
public void Only_posts_are_allowed_to_my_action()
{
var method = typeof(MyController).GetMethod("MyAction");
var attribute = method.GetCustomAttributes(typeof(AcceptVerbsAttribute),false)
.Cast<AcceptVerbsAttribute>()
.SingleOrDefault();
Assert.IsNotNull( attribute );
Assert.AreEqual( 1, attributes.Count() );
Assert.IsTrue( attributes.Contains( HttpVerbs.Post ) );
}