You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试中Directory.GetCurrentDirectory抛出DirectoryNotFoundException问题咨询

问题原因

单元测试的默认运行目录和Web项目的运行目录不一致,测试执行路径下不存在wwwroot/html/myfile.html对应的目录结构,所以调用Directory.GetCurrentDirectory()拼接路径后读取文件会触发目录不存在异常。

可行解决方案

方案1:抽象文件系统依赖,支持Mock(可维护性最优)

不要直接调用静态的Directory、File类,将文件操作抽象为接口注入到Service中,单元测试时可以自由Mock接口返回值,避免依赖真实文件系统。

实现步骤:

  • 定义抽象接口
public interface IFileSystem
{
    string GetCurrentDirectory();
    string ReadAllText(string path);
}
  • 实现真实运行时的版本
public class RealFileSystem : IFileSystem
{
    public string GetCurrentDirectory() => Directory.GetCurrentDirectory();
    public string ReadAllText(string path) => File.ReadAllText(path);
}
  • 改造Service类,通过构造函数注入IFileSystem
public class Service
{
    private readonly ISomeRepository _someRepository;
    private readonly IFileSystem _fileSystem;

    // 构造函数注入依赖
    public Service(ISomeRepository someRepository, IFileSystem fileSystem)
    {
        _someRepository = someRepository;
        _fileSystem = fileSystem;
    }

    public async Task<ReponseViewModel> TestedMethod(userData vm)
    {
        var anything = await _someRepository.GetSomething(vm.Email);
        var template = GetTemplate(url);
        return something;
    }

    private string GetTemplate(string url)
    {
        var template = _fileSystem.ReadAllText(
                        Path.Combine(
                            _fileSystem.GetCurrentDirectory(),
                            "wwwroot",
                            "html",
                            "myfile.html"));
        return template;
    }
}
  • 单元测试中Mock IFileSystem的返回值
[Fact]
public async Task someMethod()
{
    // Arrange
    var userData = new userData
    {
        Email = "test@test.com"
    };

    _someRepository.Setup(x => x.GetSomething(It.IsAny<string>())).ReturnsAsync(Faker());
    // Mock文件系统,直接返回测试用的模板内容,不需要真实文件
    var mockFileSystem = new Mock<IFileSystem>();
    mockFileSystem.Setup(x => x.ReadAllText(It.IsAny<string>())).Returns("测试用的模板内容");

    var service= new Service(_someRepository.Object, mockFileSystem.Object);

    // Act
    var result = await service.TestedMethod(userData);

    // Assert
    Assert.False(result.Success);
}

方案2:直接修改当前工作目录(无需改动业务代码)

Directory.GetCurrentDirectory()的返回值和Environment.CurrentDirectory完全一致,直接在测试Arrange阶段修改该属性值为你想要的路径即可,测试结束后记得恢复原值避免影响其他测试:

[Fact]
public async Task someMethod()
{
    // 保存原有工作目录
    var originalDir = Environment.CurrentDirectory;
    try
    {
        // 设置为你存放测试文件的目录,比如项目根目录路径
        Environment.CurrentDirectory = @"C:\你的项目路径";
        
        // 原有测试逻辑
        var userData = new userData
        {
            Email = "test@test.com"
        };
        _someRepository.Setup(x => x.GetSomething(It.IsAny<string>())).ReturnsAsync(Faker());
        var service= new Service();
        var result = await service.TestedMethod(userData);
        Assert.False(result.Success);
    }
    finally
    {
        // 恢复原有目录,消除全局副作用
        Environment.CurrentDirectory = originalDir;
    }
}

方案3:配置静态文件复制到测试输出目录(无需改动代码)

将Web项目中wwwroot/html/myfile.html文件的属性设置为如果较新则复制到输出目录,同时在单元测试项目中也按照相同层级创建wwwroot/html目录存放测试用的html文件,同样设置复制属性,单元测试运行时输出目录就会存在对应的文件结构,不会触发目录不存在异常。

内容的提问来源于stack exchange,提问作者leafar29

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 11:36:05