Rhino Mocks测试文件系统io
本文关键字:io 文件系统 测试 Mocks Rhino | 更新日期: 2023-09-27 18:19:27
我有一个应用程序,它获取一个文件字典(文件类型和文件名列表),并将文件从原始目录复制到另一个位置。我已经有了复制过程的基本代码,但我需要做一些单元测试,以便它尽可能健壮。
我有一个正在使用的包装类,这样我就可以测试是否按预期调用了System.IO方法,但我很难弄清楚如何形成测试,因为代码中有foreach和switch语句。下面的示例代码:
private IFileSystemIO _f;
public CopyFilesToDestination(IFileSystemIO f){
_f = f;
}
public void Cpy_Files(Dictionary<string, List<string>> files)
{
// get a list of the file types in the directory
var listOfFileTypes = new List<string>(files.Keys);
foreach (var fileType in listOfFileTypes){
var fileList = files[fileType].ToList();
foreach (var file in fileList){
switch(fileType){
case ".txt":
_f.Copy(file, @"c:'destination'text");
break;
case ".dat":
_.Copy(file, @"c:'destination'data");
break;
}
}
}
}
为了测试以上内容,我曾想过我会使用一个模拟字典对象,设置一个文件类型和路径列表:
public virtual Dictionary<string, List<string>> FakeFiles(){
return fakeDictionary = new Dictionary<string, List<string>>(){
{".txt", new List<string>(){
"c:'test'file1.txt",
"c:'test'file2.txt"
}
},
{".dat", new List<string>(){
"c:'test'file1.dat",
"c:'test'file2.dat"
}
};
}
}
我提出的第一个测试看起来是这样的:
[Test]
public void Should_Copy_Text_Files(){
var dictionary = new FakeDictionary().FakeFiles();
var mockObject = MockRepository.GenerateMock<IFileSystemIO>();
var systemUnderTest = new CopyFileToDestination(mockObject);
systemUnderTest.Cpy_Files(dictionary);
// I think this means "test the operation, don't check the values in the arguments" but I also think I'm wrong
mockObject.AssertWasCalled(f => f.Copy("something", "something"), o => o.IgnoreArguments());
}
我的第一个问题是:如何测试特定的文件类型,如".txt"?那么我该如何测试循环呢?我知道我只有两个条目,我可以利用它来形成测试吗?怎样
我想我可能已经接近解决方案了,但我已经没有时间/耐心去寻找了。非常感谢您的帮助。谢谢Jim
我尝试使用Roberts解决方案,但正如我所说,我有太多不同的文件类型,无法单独设置每个测试用例。我尝试的下一件事是设置一个TestCaseSource,但每次我为此运行测试时,它都会将测试标记为忽略:
[Test, TestCaseSource(typeof(FakeDictionary), "TestFiles")]
public void Cpy_Files_ShouldCopyAllFilesInDictionary(string extension, string fielName) {
// Arrange
var mockObject = MockRepository.GenerateMock<IFileSystemIO>();
var systemUnderTest = new CopyFileToDestination(mockObject);
// Act
systemUnderTest.Cpy_Files(dictionary);
// Assert
mockObject.AssertWasCalled(f => f.Copy(extension, fileName));
}
数据来源如下:
public static Dictionary<string, string> TestFiles{
get
{
return new Dictionary<string, string>()
{
{".txt",
"C:''test''test1.txt"},
{".txt",
"c:''test''test2.txt"}
};
}
}
我最终得出的是使用Rhino中的时间重复选项,非常简单:
[Test]
public void Cpy_Files_ShouldCopyAllFilesInDictionary(){
// Arrange
var mockObject = MockRepository.GenerateMock<IFileSystemIO>();
var systemUnderTest = new CopyFileToDestination(mockObject);
// Act
systemUnderTest.Cpy_Files(dictionary);
// Assert
// I know how many objects are in my fake dictionary so I set the times to repeat as a const
const int timesToRepeat = 2;
// now I just set the values below. I am not testing file names so the test will ignore arguments
mockObject.AssertWasCalled(f => f.Copy("",""), options => options.Repeat.Times(timesToRepeat).IgnoreArguments());
}
我希望这能帮助其他有类似问题的人。
我会尝试使用TestCase
属性:
[TestCase(".txt", "c:'test'file1.txt")]
[TestCase(".txt", "c:'test'file2.txt")]
[TestCase(".dat", "c:'test'file1.dat")]
[TestCase(".dat", "c:'test'file2.dat")]
public void Should_Copy_Text_Files(string extension, string fileName){
var dictionary = new FakeDictionary().FakeFiles();
var mockObject = MockRepository.GenerateMock<IFileSystemIO>();
var systemUnderTest = new CopyFileToDestination(mockObject);
systemUnderTest.Cpy_Files(dictionary);
mockObject.AssertWasCalled(f => f.Copy(extension, fileName));
}
这将分别为每个TestCase
属性运行测试,并将其包含的参数传递到测试方法中。这样,您就可以测试字典中的每个项是否是"复制的",而无需在同一测试中使用多个断言。