Search code examples
asp.net-mvcunit-testingmoqhttppostedfilebase

Mocking HttpPostedFileBase and InputStream for unit-test


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?


Solution

  • 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 :)