这更多的是一个噱头,因为我希望实现我的单元测试的完全覆盖。
这是关于FileFinder()
方法的。此方法查找文件夹中的文件并创建相应的增量命名。
现在我被告知应该有可能(无论出于什么原因)999,998个文件可能在这个文件夹中。
因此,如果检测到有一个文件被调用,例如job_999999.something
,那么它应该返回一个空字符串。
相应的代码段如下所示:
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万个文件被创建?如果有可能的话,我是不是必须写一个把所有东西都拉回去的方法,或者根本就没有这种可能性?
还是一般都有办法“骗”这个代码点?
在这种情况下,您的方法被硬编码为使用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
}
将allexistingfiles
列表创建移动到一个返回list
的方法中,然后您只需要模拟它并为您的测试场景返回不同的列表--包含job_99999.something
的列表,不包含它的列表,等等。
在单元测试流中添加某种机制来生成这些列表,使它成为集成测试,而不是单元测试,因为它打破了测试代码单元的想法。
连接应用程序与外部API(文件系统、数据库等)的所有内容都不是单元测试的主题。(如果您愿意,您仍然可以自动化它的测试,但这是一个不同的主题)。