文件IO的单元测试方法
本文关键字:测试方法 单元 IO 文件 | 更新日期: 2023-09-27 18:13:21
我正在努力养成写单元测试的习惯,我以前写过一些,但它们通常都是非常基本的…我想开始转向TDD,因为我想提高我的代码质量(设计和结构)——减少耦合,同时希望减少溜进可测试构建的回归数量。
我开始做一个相对简单的项目。生成的程序监视一个文件夹,然后对该文件夹中的文件进行操作。
下面是从项目中提取的一些典型代码示例:
private string RestoreExtension(String file)
{
var unknownFile = Path.GetFileName(file);
var ignoreDir = Path.GetDirectoryName(file) + "''Unknown";
string newFile;
//We need this library for determining mime
if (CheckLibrary("urlmon.dll"))
{
AddLogLine("Attempting to restore file extension");
var mime = GetMimeType(BufferFile(file, 256));
var extension = FileExtensions.FindExtension(mime);
if (!String.IsNullOrEmpty(extension))
{
AddLogLine("Found extension: " + extension);
newFile = file + "." + extension;
File.Move(file, newFile);
return newFile;
}
}
else
{
AddLogLine("Unable to load urlmon.dll");
}
AddLogLine("Unable to restore file extension");
if (!Directory.Exists(ignoreDir))
{
Directory.CreateDirectory(ignoreDir);
}
var time = DateTime.Now;
const string format = "dd-MM-yyyy HH-mm-ss";
newFile = ignoreDir + "''" + unknownFile + "-" + time.ToString(format);
File.Move(file, newFile);
return String.Empty;
}
问题:
如何使用IO测试方法?我真的不想使用一个真正的文件,因为这将是缓慢的(和更多的集成测试?),但我真的看不到其他方法。我可以添加一个可切换的IO抽象层,但这听起来可能会不必要地使代码复杂化……
这样的项目值得进行单元测试吗?我的意思是,是不是太简单了。一旦你去掉。net和第三方库调用,剩下的就不多了……那么,使其可测试的工作量是否意味着它不是一个好的测试候选?
这个项目中的很多方法都是私有的,因为这个项目恰好是一个windows服务。我读过你应该只测试外部可见的方法(公共或通过接口暴露),但在这种情况下,我不太可能公开我自己的任何方法。那么这个项目是否值得测试(因为我可能需要将方法访问修饰符更改为public或添加一些属性以便NUnit可以看到它们)?
public class FileHandler : IFileHandler
{
public string GetFilename(string name)
{
return System.IO.GetFileName(name);
}
public string GetDirectoryName(string directory)
{
return System.IO.GetDirectoryName(directory);
}
}
public interface IFileHandler
{
string GetFilename(string name);
string GetDirectoryName(string directory);
}
在测试中的方法中,您只针对接口进行编程。当您运行单元测试时,您将使用返回预定义值的模拟对象。为此,您可以使用Moq。
这是一点工作要做,但你不需要测试文件I/O。
最好1月
如何使用IO测试方法?
通过在。net的IO库上引入抽象,然后在应用程序中使用真实实现(BCL),在单元测试中使用假实现(mock)。这样的抽象是相当简单的编写自己,但这些项目已经存在(例如。所以重新发明轮子是没有意义的,尤其是在这种琐碎的事情上。
这是正确的,在测试中你想使用fake (mock)对象。我真的不想使用一个真正的文件,因为这会很慢
这样的项目值得进行单元测试吗?
每个项目都值得测试,你将以一种或另一种方式测试它(在最极端的情况下,通过手动执行应用程序并进行良好的老式点击等待测试)。
请注意,手动测试复杂解析器方法的10个边缘情况几乎总是太耗时,每次都需要加载大文件并等待结果。这就是隔离环境中的自动化测试能提供很大帮助的地方。你的代码文件系统、web服务也是一样,它们在你进入实际的业务逻辑之前都会引入大量的开销。必须隔离。
这个项目中的很多方法都是私有的(…)我读过你应该只测试外部可见的方法
正确,你应该测试公共合同。然而,如果私有的东西变得足够大,可以对它进行测试,大多数情况下,这是一个很好的指标,它也足够大,可以把它放在自己的类中。请注意,仅为单元测试使用更改成员访问修饰符并不是最好的主意。几乎总是提取类/方法重构更好。
你可以使用Microsoft Fakes。首先为System.dll或任何其他包生成一个假程序集,然后模拟预期的返回,如:
using Microsoft.QualityTools.Testing.Fakes;
...
using (ShimsContext.Create())
{
System.IO.Fakes.ShimDirectory.ExistsString = (p) => true;
System.IO.Fakes.ShimFile.MoveStringString = (p,n) => {};
// .. and other methods you'd like to test
var result = RestoreExtension("C:'myfile.ext");
// then you can assert with this result
}
我对TDD也很陌生,但我想我可以给你一些建议:
-
关于IO测试。您可以使用模拟对象。为要测试的方法创建一个模拟,并将其与实际传递的值进行比较。在Moq框架中,它看起来像这样:
var mock = new Mock<IRepository<PersonalCabinetAccount>>(); mock.Setup(m => m.RemoveByID(expectedID)) .Callback((Int32 a) => Assert.AreEqual(expectedID, a)); var account = new PersonalCabinetAccount {ID = myID}; var repository = mock.Object; repository.RemoveByID(account.myId);
-
绝对是的。如果你想养成一种习惯,我想你需要测试一切。
-
你可以使用InternalsVisibleTo属性来避免可见性问题。
外部可见的测试方法
我认为这是关于企业编程的。只需要花点时间在你自己的可信代码上。
希望我的观点对你有帮助。