C
C#•3y ago
HimmDawg

Mocking FileStream for integration testing

I made a simple integration test that tests some functionality after calling an API endpoint. In my api client, I have this function UploadDocumentAsync(string filePath)
public async Task<RestResponse<int>> UploadDocumentAsync(string filePath)
{
using var formData = new MultipartFormDataContent();

var fileStream = new StreamContent(new FileStream(filePath));
var fileName = Path.GetFileName(filePath);

// ...
}
public async Task<RestResponse<int>> UploadDocumentAsync(string filePath)
{
using var formData = new MultipartFormDataContent();

var fileStream = new StreamContent(new FileStream(filePath));
var fileName = Path.GetFileName(filePath);

// ...
}
As you can see, this function expects a string as an argument. To make the function testable though, I'd need an abstraction for FileStream (which I know exists as a NuGet package) and inject it into the function. The question is: Is that better? I know it doesn't sound too bad, but calling the function with a FileStream instead of a string takes away a bit of comfort imo. I don't know if that's just silly goblinresHide . Or maybe you guys know another way to test such a function
6 Replies
cap5lut
cap5lut•3y ago
i think the simplest way would be to just create a temp file with the desired content and pass its path to the method
HimmDawg
HimmDawgOP•3y ago
Hmmm, in that case I should just create some random bytes as data and pass that. I don't wanna bother whether the file was really created etc 😄
cap5lut
cap5lut•3y ago
well, the only other way i can think of would be creating a public async Task<RestResponse<int>> UploadDocumentAsync(string fileName, Stream stream); that does the actual work and which is called by ur current implementation. then u could use for example a MemoryStream instead of a real file
HimmDawg
HimmDawgOP•3y ago
Right, I fiddled around a bit and just used System.IO.Abstractions and System.IO.Abstractions.TestingHelpers I injected an IFileSystem into my ApiClient
public ApiClient(HttpClient client, IFileSystem fileSystem)
{
_client = client;
_fileSystem = fileSystem;
}
public ApiClient(HttpClient client, IFileSystem fileSystem)
{
_client = client;
_fileSystem = fileSystem;
}
and changed the method to
public async Task<RestResponse<int>> UploadDocumentAsync(string filePath)
{
using var formData = new MultipartFormDataContent();

var fileStream = new StreamContent(_fileSystem.File.OpenRead(filePath));
var fileName = Path.GetFileName(filePath);

// ...
}
public async Task<RestResponse<int>> UploadDocumentAsync(string filePath)
{
using var formData = new MultipartFormDataContent();

var fileStream = new StreamContent(_fileSystem.File.OpenRead(filePath));
var fileName = Path.GetFileName(filePath);

// ...
}
And in my test, I created a MockFileSystem which implements IMockFileDataAccessor, which implements IFileSystem
// Arrange
string fakePath = "HelloWorld.txt";
byte[] fakeContent = Encoding.UTF8.GetBytes("Fake file content");

MockFileSystem mockFileSystem = new MockFileSystem();
mockFileSystem.AddFile(fakePath, new MockFileData(fakeContent));

_sut = new ApiClient(client, mockFileSystem);

// Act
var response = await _sut.UploadDocumentAsync(fakePath);
// Arrange
string fakePath = "HelloWorld.txt";
byte[] fakeContent = Encoding.UTF8.GetBytes("Fake file content");

MockFileSystem mockFileSystem = new MockFileSystem();
mockFileSystem.AddFile(fakePath, new MockFileData(fakeContent));

_sut = new ApiClient(client, mockFileSystem);

// Act
var response = await _sut.UploadDocumentAsync(fakePath);
Just if somebody has a similar issue foxNosy
MODiX
MODiX•3y ago
That command had an error
UnknownCommand: Unknown command.
Remove your reaction to delete this message
HimmDawg
HimmDawgOP•3y ago
oh well ¯\_(ツ)_/¯

Did you find this page helpful?