i am learning unit testing. How to unit test this method using nunit and rhino mock ?
public ActionResult PrintCSV(Byte[] bytes, string fileName)
{
var file = File(bytes, "application/vnd.ms-excel");
var cd = new System.Net.Mime.ContentDisposition()
{
CreationDate = DateTime.Now,
FileName = fileName,
Inline = false
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return file;
}
You will need to mock the HttpContext. Here's an example (it's MSTest but I guess it won't be a hell lot of a pain to port to NUnit - all you need is to rename a couple of attributes):
[TestMethod]
public void PrintCSV_Should_Stream_The_Bytes_Argument_For_Download()
{
// arrange
var sut = new HomeController();
var bytes = new byte[] { 1, 2, 3 };
var fileName = "foobar";
var httpContext = MockRepository.GenerateMock<HttpContextBase>();
var response = MockRepository.GenerateMock<HttpResponseBase>();
httpContext.Expect(x => x.Response).Return(response);
var requestContext = new RequestContext(httpContext, new RouteData());
sut.ControllerContext = new ControllerContext(requestContext, sut);
// act
var actual = sut.PrintCSV(bytes, fileName);
// assert
Assert.IsInstanceOfType(actual, typeof(FileContentResult));
var file = (FileContentResult)actual;
Assert.AreEqual(bytes, file.FileContents);
Assert.AreEqual("application/vnd.ms-excel", file.ContentType);
response.AssertWasCalled(
x => x.AppendHeader(
Arg<string>.Is.Equal("Content-Disposition"),
Arg<string>.Matches(cd => cd.Contains("attachment;") && cd.Contains("filename=" + fileName))
)
);
}
As you can see there's a bit of a plumbing code here to setup the test. Personally I use MvcContrib.TestHelper as it simplifies a lot of this plumbing code and makes the test more readable. Check this out:
[TestClass]
public class HomeControllerTests : TestControllerBuilder
{
private HomeController sut;
[TestInitialize]
public void TestInitialize()
{
this.sut = new HomeController();
this.InitializeController(this.sut);
}
[TestMethod]
public void PrintCSV_Should_Stream_The_Bytes_Argument_For_Download()
{
// arrange
var bytes = new byte[] { 1, 2, 3 };
var fileName = "foobar";
// act
var actual = sut.PrintCSV(bytes, fileName);
// assert
var file = actual.AssertResultIs<FileContentResult>();
Assert.AreEqual(bytes, file.FileContents);
Assert.AreEqual("application/vnd.ms-excel", file.ContentType);
this.HttpContext.Response.AssertWasCalled(
x => x.AppendHeader(
Arg<string>.Is.Equal("Content-Disposition"),
Arg<string>.Matches(cd => cd.Contains("attachment;") && cd.Contains("filename=" + fileName))
)
);
}
}
Now the test is much more clear as we can immediately see the initialization phase, the actual invoke of the method under test and the assertion.
Remark: All this being said I don't quite see the point of a controller action that takes a byte array as argument just to stream it back to the client. I mean in order to invoke it the client needs to already have the file, so what's the point? But I guess that was just for illustration purposes. In your actual method the byte array is not passed as argument but is retrieved inside your controller action from some external dependency. In this case you could mock this dependency as well (assuming of course you have properly architected your layers and they are sufficiently weakly coupled).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With