Actually the blog title is somewhat misleading; the objective was to create a method that we can pass a FileUpload control into and it will save it to a temporary file (guid filename) and return the name so that we can process it further.
Unfortunately this objective became quite complicated once we threw TDD into the mix. We had to throw out what could have been an easy fileUpload.SaveAs(tempFile) command and substitute it with a process that we can Unit Test. TypeMock helps us do this quite nicely
Below is the process we will be using from ASP.NET and our Unit Test:
/// <summary>
/// Save the FileUpload data as a temp file
/// </summary>
/// <param name="sender"></param>
/// <param name="fileUpload"></param>
/// <returns></returns>
public string SaveFileUploadAsTempFile(FileUpload fileUpload)
{
// Generate a Temp file in the App_Data\Temp folder
// and return the file name
string tempFile = GetTempFile();
// Store the FileUpload control's InputStream (the file)
// to a fileData stream. We do it this way for Unit Testing
// purposes
Stream fileData = fileUpload.PostedFile.InputStream;
// Use the Stream's StrToFile extension to save the contents
// to our temp file
fileData.StrToFile(tempFile);
// Return the name of the temp file that holds our
// file contents
return tempFile;
}
I commented the unit test heavily so I'll just post the Unit Test in its entirety for your review:
using System;
using System.IO;
using System.Web;
using System.Web.UI.WebControls;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TypeMock;
using HttpUtility.Tests.Base;
using HttpUtility.Storage;
// Holds our string and stream extensions for StrToFile()
using Library.Utility.Extensions;
namespace HttpUtility.Tests
{
/// <summary>
/// Summary description for FileUploadFixture
/// </summary>
[TestClass]
public class FileUploadFixture : TestBase
{
public FileUploadFixture() {}
[TestMethod]
public void FileUpload_ControlCanWriteToAppData()
{
// The TestBase:HttpContextBase constructor will
// create a HttpContext.Current if it is null BLOGGED HERE
HttpContext MockContext = HttpContext.Current;
// Assert that we have a MockContext
Assert.IsNotNull(MockContext,
"HttpContextBase should create HttpContext");
// When the context is retrieved the PhysicalPath
// property of our TestBase class will be set
Assert.IsNotNull(PhysicalPath);
// Dynamically generate our MockFolderPath using the
// TestBase:HttpContextBase.PhysicalPath property
MockFolderPath = PhysicalPath.Replace("default.aspx", "App_Data");
// Instantiate our file Utility class
FileUploadUtil fileUploadUtil = new FileUploadUtil();
// Setup the TypeMock recorder
// When MapPath("App_Data") is requested, supply our
// MockFolderPath (public static string in TestBase)
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
// GetTempFile() will request this - we'll return
// our MockFolderPath when it does
HttpContext.Current.Server.MapPath("App_Data");
recorder.Return(MockFolderPath);
}
// Use the fileUploadUtil to get Temp file in App_Data\Temp
string app_dataPath = fileUploadUtil.GetTempFile();
// Write mockData to temp file using our string extension
mockData.StrToFile(app_dataPath);
// Ensure our mockData file exists so we can
// pull it into a MockStream
Assert.IsTrue(File.Exists(app_dataPath));
// Read temp file containing mockData into file stream
FileInfo fileInfo = new FileInfo(app_dataPath);
FileStream MockStream = fileInfo.OpenRead();
// Instantiate our mock FileUpload control
FileUpload MockFileUploadControl = new FileUpload();
// Setup the TypeMock recorder
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
// GetTempFile() will request this - we'll return
// our MockFolderPath when it does
HttpContext.Current.Server.MapPath("App_Data");
recorder.Return(MockFolderPath);
// When the contents from the PostedFile.InputStream is
// requested we'll return our MockStream (set above to
// the contents of app_dataPath)
recorder.ExpectAndReturn(
MockFileUploadControl.PostedFile.InputStream,
MockStream);
}
// Call our FileUploadUtil method that will save the
// FileUpload control's contents to a temporary file
string savedFile = fileUploadUtil
.SaveFileUploadAsTempFile(MockFileUploadControl);
// Retrieve the file just saved
string savedXML = savedFile.FileToStr();
// Assert that it is equal to the data that was in our
// MockStream
Assert.AreEqual(mockData, savedXML);
MockManager.Verify();
}
private TestContext testContextInstance;
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
}
}
Source code available HERE Change Set: 40565