问题
I want to test the following line of code:
...
Bitmap uploadedPicture = Bitmap.FromStream(model.Picture.InputStream) as Bitmap;
...
Picture is a property in my model type HttpPostedFileBase. So I would like to mock a HttpPostedFileBase property for unit-testing:
model.Picture = new Mock<HttpPostedFileBase>().Object;
No problem at all.
Now I have to mock the InputStream, otherwise it's null:
model.Picture.InputStream = new Mock<Stream>().Object;
This isn't working as the InputStream is read-only (hasn't a setter method):
public virtual Stream InputStream { get; }
Is there a good and clean way to handle this problem? One solution would be to override HttpPostedFileBase in a derived class for my unit-test. Any other idea?
回答1:
Hi there :) I did something like,
[TestInitialize]
public void SetUp()
{
_stream = new FileStream(string.Format(
ConfigurationManager.AppSettings["File"],
AppDomain.CurrentDomain.BaseDirectory),
FileMode.Open);
// Other stuff
}
And on the Test itself,
[TestMethod]
public void FileUploadTest()
{
// Other stuff
#region Mock HttpPostedFileBase
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var files = new Mock<HttpFileCollectionBase>();
var file = new Mock<HttpPostedFileBase>();
context.Setup(x => x.Request).Returns(request.Object);
files.Setup(x => x.Count).Returns(1);
// The required properties from my Controller side
file.Setup(x => x.InputStream).Returns(_stream);
file.Setup(x => x.ContentLength).Returns((int)_stream.Length);
file.Setup(x => x.FileName).Returns(_stream.Name);
files.Setup(x => x.Get(0).InputStream).Returns(file.Object.InputStream);
request.Setup(x => x.Files).Returns(files.Object);
request.Setup(x => x.Files[0]).Returns(file.Object);
_controller.ControllerContext = new ControllerContext(
context.Object, new RouteData(), _controller);
// The rest...
}
Hope this can provide an idea to your solution :)
回答2:
I've just been working on something similar and wanted to add the following to @TiagoC13's answer.
My system under test was a file service I'm writing, one of the requirements being to test that a file has the correct dimensions. Note, the hard-coded filename. This exists as a folder and file in my Test Project. The file's properties are as follows: Build Action : Embedded Resource and Copy to Output Directory: Copy if newer (although Copy Always should work OK)
When the project is built the testimage.jpg and its folder are added to the bin where the test then finds it.
Also note the fileStream.Close(); this releases the file so you can have a number of similar tests in the same suite.
Hope this is of help.
using Moq;
using NUnit.Framework;
using System.Web;
[Test]
public void IsValidFile() {
string filePath = Path.GetFullPath(@"testfiles\testimage.jpg");
FileStream fileStream = new FileStream(filePath, FileMode.Open);
Mock<HttpPostedFileBase> uploadedFile = new Mock<HttpPostedFileBase>();
uploadedFile
.Setup(f => f.ContentLength)
.Returns(10);
uploadedFile
.Setup(f => f.FileName)
.Returns("testimage.jpg");
uploadedFile
.Setup(f => f.InputStream)
.Returns(fileStream);
var actual = fileSystemService.IsValidImage(uploadedFile.Object, 720, 960);
Assert.That(actual, Is.True);
fileStream.Close();
}
回答3:
There is no need to create a stream from opening a file on disk. Actually I think that's a pretty horrible solution. A working test stream can be created easily enough in-memory.
var postedFile = new Mock<HttpPostedFileBase>();
using (var stream = new MemoryStream())
using (var bmp = new Bitmap(1, 1))
{
var graphics = Graphics.FromImage(bmp);
graphics.FillRectangle(Brushes.Black, 0, 0, 1, 1);
bmp.Save(stream, ImageFormat.Jpeg);
postedFile.Setup(pf => pf.InputStream).Returns(stream);
// Assert something with postedFile here
}
来源:https://stackoverflow.com/questions/15622153/mocking-httppostedfilebase-and-inputstream-for-unit-test