当前位置: 首页 > 知识库问答 >
问题:

通过单元测试在C#中模拟创建多个文件

凌琦
2023-03-14

这更多的是一个噱头,因为我希望实现我的单元测试的完全覆盖。

这是关于FileFinder()方法的。此方法查找文件夹中的文件并创建相应的增量命名。

现在我被告知应该有可能(无论出于什么原因)999,998个文件可能在这个文件夹中。

因此,如果检测到有一个文件被调用,例如job_999999.something,那么它应该返回一个空html" target="_blank">字符串。

相应的代码段如下所示:

var allFiles = new List<string>();
allFiles.AddRange(Directory.GetFiles(SomeImagesPath));
allFiles.AddRange(Directory.GetFiles(TempFolderPathForSomething));

var allExistingFiles = allFiles.Select(x =>
                                              {
                                                 var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(x);
                                                 return fileNameWithoutExtension.TrimStart('V', 'v').TrimStart('S', 's', 'P', 'p', 'V', 'v', 'I', 'i');
                                              })
                                      .ToList();
                                      
var i = 0;
while (i < 1000000)
{
   i++;
   if (!allExistingFiles.Contains($"{i:000000}"))
      break;
   if (i == 999999)
      return string.Empty;
}

我通过单元测试覆盖了所有内容,只有if的情况对我来说是不可能的。

就我个人而言,我认为这也是毫无意义的,但是我想知道(没有给你命名之前和之后的功能)是否有一种方法通过单元测试来模拟100万个文件被创建?如果有可能的话,我是不是必须写一个把所有东西都拉回去的方法,或者根本就没有这种可能性?

还是一般都有办法“骗”这个代码点?

共有2个答案

钦德佑
2023-03-14

allexistingfiles列表创建移动到一个返回list 的方法中,然后您只需要模拟它并为您的测试场景返回不同的列表--包含job_99999.something的列表,不包含它的列表,等等。
在单元测试流中添加某种机制来生成这些列表,使它成为集成测试,而不是单元测试,因为它打破了测试代码单元的想法。
连接应用程序与外部API(文件系统、数据库等)的所有内容都不是单元测试的主题。(如果您愿意,您仍然可以自动化它的测试,但这是一个不同的主题)。

翟元凯
2023-03-14

在这种情况下,您的方法被硬编码为使用system.io.directory。这意味着您必须针对实际的文件系统进行编码。这意味着当您进行单元测试时,它将会命中实际的文件系统。那可不理想。单元测试不应具有外部依赖项。

我们可以通过对抽象进行编码来修复这种情况。System.io.abstractions库已经为我们提供了预构建的抽象和具体实现。这允许我们选择何时使用真实的文件系统(在正常运行时),何时使用文件系统的模拟(在单元测试期间)。

readonly IFileSystem _fileSystem;

// I'm assuming you use Dependency Injection.
// To hit the real system, your app should inject a System.IO.Abstractions.FileSystem.
// To test, you can pass in a System.IO.Abstractions.TestingHelpers.MockFileSystem
public MyClass(IFileSystem fileSystem)
{
    _fileSystem = fileSystem;
}

public string FileFinder()
{
    var allFiles = new List<string>();
    allFiles.AddRange(_fileSystem.Directory.GetFiles(SomeImagesPath));
    allFiles.AddRange(_fileSystem.Directory.GetFiles(TempFolderPathForSomething));

    var allExistingFiles = allFiles.Select(x =>
                                                  {
                                                     var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(x);
                                                     return fileNameWithoutExtension.TrimStart('V', 'v').TrimStart('S', 's', 'P', 'p', 'V', 'v', 'I', 'i');
                                                  })
                                          .ToList();
                                          
    var i = 0;
    while (i < 1000000)
    {
       i++;
       if (!allExistingFiles.Contains($"{i:000000}"))
          break;
       if (i == 999999)
          return string.Empty;
    }
}

然后您的测试变为:

[UnitTest]
public void MyTest()
{
    //arrange
    var mockFileSystem = new System.IO.Abstractions.TestingHelpers.MockFileSystem();
    //add fake files as needed to mockFileSystem
    var myClass = new MyClass(mockFileSystem);
    
    //act
    string result = myClass.FileFinder();
    
    //assert
    //make assertions here about your result
    
}
 类似资料:
  • 为了让单元测试跑一个批处理的任务,这个框架必须加载这个任务的ApplicationContext,两个注解的触发方式: @RunWith(SpringJUnit4ClassRunner.class):表明这个类需要使用Spring的测试工具 @ContextConfiguration(locations = {…}):表明哪些xml文件包含ApplicationContext @RunWith

  • 我在尝试包装我的代码以用于单元测试时遇到了一些问题。问题是。我有接口IHttpHandler: 现在很明显,我将在Connection类中有一些方法,这些方法将从my后端检索数据(JSON)。但是,我想为这个类编写单元测试,显然我不想编写针对真实后端的测试,而是一个被嘲弄的测试。我曾尝试谷歌一个很好的答案,但没有很大的成功。我以前可以并且曾经使用过Moq来模拟,但是从来没有在像HttpClient

  • 我有一个Quarkus项目,我将大部分业务逻辑放在服务中,也就是使用@ApplicationScoped注释的可注入bean中,所有CRUD操作都在其中进行。在JAX-RS资源文件本身中,大部分逻辑只是验证,通常使用整个验证bean。这意味着我们需要在测试资源时模拟注入的服务,以防止单元测试成为本质上的集成测试。我们这样做有这样一个结构(示例项目); 文件模拟欢迎服务。java又是这样的: 我们的

  • 问题内容: 我正在为启动a 并使用返回的诺言执行一些逻辑的控制器编写单元测试。我可以测试触发$ modal的父控制器,但是我一生无法弄清楚如何模拟成功的诺言。 我尝试了多种方法,包括使用和强制履行承诺。但是,我得到的最接近的结果是与本 SO帖子中的最后一个答案相似的东西。 我已经在“旧的” 模式中看到了几次这样的问题。在“新” 模式下,我找不到太多的方法。 一些指针将不胜感激。 为了说明问题,我使

  • 我开始在我的项目中实践TDD,作为背景,它也包含遗留代码。我们使用Mockito作为一个模拟框架,并遵循Spring MVC方法。 有时,类用许多不同的对象作为属性实现。这些服务中有一些简单的方法,例如。 将使用许多对象来完成其职责 更新并保存事务 推进业务流程 关闭其他挂起的操作 但是,在执行这些操作时,该方法需要调用不同的来获取和更新事务、获取业务流程ID、获取挂起的事务(并保存其更新)。这意

  • 问题内容: 我正在尝试测试角度服务,该服务通过使用茉莉花服务对DOM进行一些操作。假设它只是将一些指令附加到元素上。 这样的服务可能看起来像 我想这样测试 因此,问题是创建这种模拟的最佳方法是什么? 进行真正的测试会使我们在每次测试后清理时遇到很多麻烦,而且看起来并不可行。 我还尝试过在每次测试之前创建一个新的真实文档实例,但最终都失败了。 创建如下所示的对象并检查变量的工作原理,但看起来非常丑陋