asp.net C# UnitTests模拟文件ReadAllBytes引发System.IO.FileNotFoundException异常

0mkxixxg  于 2023-01-22  发布在  .NET
关注(0)|答案(2)|浏览(162)

在控制器中,我有一个返回FileStreamResult对象的操作结果,在此之前,该操作使用File类的byte[] ReadAllBytes(string path)
行动结果是:

public async Task<IActionResult> Download(string path)
{
    var myfile = System.IO.File.ReadAllBytes(path);

    MemoryStream stream = new MemoryStream(myfile);

    return new FileStreamResult(stream, "application/pdf");
}

在我的xUnit测试项目中,我使用Moq进行设置。
模拟:

using IFileSystem = System.IO.Abstractions.IFileSystem;

private readonly Mock<IFileSystem> _fileSystem = new Mock<IFileSystem>();

试验方法:

[Fact]
public async Task Download_ShouldReturnPdfAsFileStreamResult_WhenIsFoundByPath()
{
    //Arrange
    var expected = new byte[]
    {
        68, 101, 109, 111, 32, 116, 101, 120, 116, 32, 99, 111, 110, 116,
        101, 110, 255, 253, 0, 43, 0, 32, 0, 115, 0, 111, 0, 109, 0, 101,
        0, 32, 0, 116, 0, 101, 0, 120, 0, 116
    };

    var path = _fixture.Create<string>();

    _fileSystem.Setup(f => f.File.ReadAllBytes(It.IsAny<string>()))
        .Returns(expected);

    //Act
    var result = await _sutController.Download(path )
        .ConfigureAwait(false) as FileStreamResult;

    //Assert
    result.Should().NotBeNull();
    //...
}

现在,当我运行测试时,我会得到这个异常:
留言:

System.IO.FileNotFoundException : Could not find file 'C:\Users\Admin\Desktop\GF\Tests\GF.Web.Controllers.Tests\bin\Debug\net6.0\Path69bdc5aa-695a-4779-b38e-12cb2df4c21a'.

  Stack Trace: 
SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
OSFileStreamStrategy.ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
FileStreamHelpers.ChooseStrategyCore(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
FileStreamHelpers.ChooseStrategy(FileStream fileStream, String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, Int64 preallocationSize)
File.ReadAllBytes(String path)
ctehm74n

ctehm74n1#

Alexandria 在评论中建议的更合理的方法是这样的:
首先开始在web和单元测试项目中安装nuget包https://www.nuget.org/packages/System.IO.Abstractions/

Install-Package System.IO.Abstractions

然后将IFileSystem插入控制器

public class DownloadsController : Controller
{
    private readonly IFileSystem _fileSystem;

    public DownloadsController(IFileSystem fileSystem)
    {
        _fileSystem = fileSystem;
    }
    ///Code ....
}

当然,在启动时配置依赖项注入
现在在控制器操作结果中使用_fileSystem.File.ReadAllBytes(path)代替System.IO.File.ReadAllBytes(path)
现在,在测试类中,只需在构造器中注入IFileSystemMock

using IFileSystem = System.IO.Abstractions.IFileSystem;
private readonly Mock<IFileSystem> _fileSystem = new Mock<IFileSystem>();

public DownloadsControllerTests()
{
      _sutController = new DownloadsController(_fileSystem.Object);
}

并设置**_文件系统.文件.读取所有字节**:

_fileSystem.Setup(f => f.File.ReadAllBytes(It.IsAny<string>()))
                .Returns(expected).Verifiable();

应为new byte[]

imzjd6km

imzjd6km2#

有一个替代的纯粹的方式来模拟(Moq),不添加任何Nuget包。实现一个接口和类。然后依赖注入接口。现在你可以在测试类中模拟。

public interface IMyHelper
  {
     byte[] ReadByteArrayFromFile(string path);
  }

  public class MyHelper:IMyHelper
 {
    public byte[] ReadByteArrayFromFile(string path)
    {
        byte[] bytes = System.IO.File.ReadAllBytes(path);
        return bytes; 
    }
 }

[TestClass]
      Mock<IMyHelper> myHelper = new Mock<IMyHelper>();
[TestInitialize]
   public void SetUp()
    {
         myHelper.Setup(x => x.ReadByteArrayFromFile(It.IsAny<string> 
        ())).Returns(new byte[123]);
    }

相关问题