I am working on a unit test for an async function that converts a list of IFormFile to a list of my own arbitrary database file classes.
The method that converts the file data to a byte array is:
internal async Task<List<File>> ConvertFormFilesToFiles(ICollection<IFormFile> formFiles)
{
var file = new File
{
InsertDateTime = DateTime.Now,
LastChangeDateTime = DateTime.Now
};
if (formFile.Length > 0)
{
using (var memoryStream = new MemoryStream())
{
await formFile.CopyToAsync(memoryStream, CancellationToken.None);
file.FileData = memoryStream.ToArray();
}
}
// ...
}
The function receives an ICollection of IFormFiles so it is mockable.
For now I have test code like this:
//Arrange
var fileConverter = new FilesConverter();
using (var fileStream = new FileStream("Files/uploadme.txt", FileMode.Open, FileAccess.Read))
{
using (var memoryStream = new MemoryStream())
{
var newMemoryStream = new MemoryStream();
fileStream.CopyTo(memoryStream);
FormFileMock.Setup(f => f.CopyToAsync(newMemoryStream, CancellationToken.None)).Returns(Task.CompletedTask);
// some other setups
//Act
var result = await fileConverter.ConvertFormFilesToFiles(new List<IFormFile> { FormFileMock.Object });
//Assert
Assert.IsTrue(result.Any());
}
}
The newMemoryStream variable is created because the function calls the CopyToAsync method with a new and empty memorystream (I'm not sure if this is necessary).
The problem is that the await formFile.CopyToAsync(memoryStream, CancellationToken.None) doesn't copy any data to the memoryStream.
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
C is a structured, procedural programming language that has been widely used both for operating systems and applications and that has had a wide following in the academic community. Many versions of UNIX-based operating systems are written in C.
I know this might be unpopular because using a mock framework is totally "in" these days, but why not simply leave the framework be framework and go the simple, easy way? You can create a FormFile
without any mocking. Just the real deal:
var fileConverter = new FilesConverter(FilesConverterLoggerMock.Object, FileDataMock.Object);
// access to a real file should really not be in a "unit" test, but anyway:
using (var stream = new MemoryStream(File.ReadAllBytes("Files/uploadme.txt"))
{
// create a REAL form file
var formFile = new FormFile(stream , 0, stream.Length, "name", "filename");
//Act
var result = await fileConverter.ConvertFormFilesToFiles(new List<IFormFile> { formFile });
//Assert
Assert.IsTrue(result.Any());
}
The problem is that the
await formFile.CopyToAsync(memoryStream, CancellationToken.None)
doesn't copy any data to thememoryStream
.
According to your setup. Nothing will actually be copied.
You just setup the call to return as completed. No actual functionality was implemented.
You'll need to add a Callback
to perform some desired functionality before returning the task.
FormFileMock
.Setup(_ => _.CopyToAsync(It.IsAny<Stream>(), CancellationToken.None))
.Callback<Stream, CancellationToken>((stream, token) => {
//memory stream in this scope is the one that was populated
//when you called **fileStream.CopyTo(memoryStream);** in the test
memoryStream.CopyTo(stream);
})
.Returns(Task.CompletedTask);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With