-
Notifications
You must be signed in to change notification settings - Fork 1
Home
This library contains a full rewrite of the standard multipart stream providers:
- System.Net.Http.MultipartFileStreamProvider → TestableMultipartFileStreamProvider
- System.Net.Http.MultipartFormDataStreamProvider → TestableMultipartFormDataStreamProvider
In normal usage, they work just like the Microsoft counterparts. The difference between the two is only evident in unit tests. Whereas the Microsoft classes require multipart file attachments to be written to the filesystem, the Testable variety offer a mockable interface based on the SystemWrapper library.
My suggestion for the design of a unit-testable Web API controller is to inject the provider via the controller constructor:
public MyController(TestableMultipartFormDataStreamProvider multipartProvider)
{
this.multipartProvider = multipartProvider;
}
From there you can construct a concrete TestableMultipartFormDataStreamProvider
in an IDependencyResolver
.
Because the Testable classes derive from MultipartStreamProvider
, usage of the provider will be exactly the same in your actions.
Unit testing controllers that depend on the Testable classes is now possible without touching the filesystem. Simply inject an IFile
mock into the provider at test-time, and (if appropriate) return a mocked stream. Here's an example with Moq:
[Test]
public void ControllerTest()
{
var path = Fixtures.CreateAnonymous<string>();
var bufferSize = Fixtures.CreateAnonymous<int>();
var fileMock = new Mock<IFile>();
var provider = new TestableMultipartFormDataStreamProvider(path, bufferSize, fileMock.Object);
var ctrl = new MyController(provider);
// exercise controller
}
The code in the library that uses IFile
are these couple of lines in TestableMultipartFileStreamProvider.GetStream
, the method that provides a Stream
instance for the content writer:
var stream_wrapper = FileWrapper.Create(fullpath, BufferSize, FileOptions.Asynchronous);
return stream_wrapper.StreamInstance;
This code (when not mocked) is wrapping File.Create
, and uses IFileStream
, also found in the SystemWrapper library.