Using MVC3.NET I have a file upload method in a controller that works fine with the following signature public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> file)
How can I unit test this with NUnit? I have looked around and everyone seems to point to Moq but I'm new to unit testing and cannot get Moq working.
I have found interesting blogs such as this: http://danielglyde.blogspot.com/2011/07/tdd-with-aspnet-mvc-3-moq-and.html but am struggling to figure out how the same might be done to 'fake' a file upload, and am also wary that a lot on moq examples that I have managed to find now seem to have deprecated code in them.
I would simply like to know how I can simulate a HttpPostedFileBase so I can test my upload code, using Moq or otherwise - I would be really grateful if someone could give me some code examples on how to do this.
The following code taken from other examples on here:
var file = new Mock<HttpPostedFileBase>();
file.Setup(f => f.ContentLength).Returns(1);
file.Setup(f => f.FileName).Returns("test.txt");
controller.upload(file);
generates the following error when I try to compile:
cannot convert from 'Moq.Mock' to
'System.Web.HttpPostedFileBase'
I have changed the method to take a singular HttpPostedFileBase for now, rather than an IEnumerable, as being able to 'mock' one is what I'm trying to focus on for the purpose of this question.
Assuming a standard file upload action:
[HttpPost]
public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> files)
{
foreach (var file in files)
{
var filename = Path.Combine(Server.MapPath("~/app_data"), file.FileName);
file.SaveAs(filename);
}
return View();
}
you could test it like this:
[Test]
public void Upload_Action_Should_Store_Files_In_The_App_Data_Folder()
{
// arrange
var httpContextMock = new Mock<HttpContextBase>();
var serverMock = new Mock<HttpServerUtilityBase>();
serverMock.Setup(x => x.MapPath("~/app_data")).Returns(@"c:\work\app_data");
httpContextMock.Setup(x => x.Server).Returns(serverMock.Object);
var sut = new HomeController();
sut.ControllerContext = new ControllerContext(httpContextMock.Object, new RouteData(), sut);
var file1Mock = new Mock<HttpPostedFileBase>();
file1Mock.Setup(x => x.FileName).Returns("file1.pdf");
var file2Mock = new Mock<HttpPostedFileBase>();
file2Mock.Setup(x => x.FileName).Returns("file2.doc");
var files = new[] { file1Mock.Object, file2Mock.Object };
// act
var actual = sut.UploadFile(files);
// assert
file1Mock.Verify(x => x.SaveAs(@"c:\work\app_data\file1.pdf"));
file2Mock.Verify(x => x.SaveAs(@"c:\work\app_data\file2.doc"));
}
Obviously all the HttpContext setup part should be externalized into a reusable class that could be called in the [SetUp]
phase of your unit test to prepare the mock context of the subject under test and to avoid repeating it in every single unit test.