我需要一些单元测试这种方法的方法。问题是FsFileGroupFile不容易被模拟,它具有复杂的构造函数要求,并且不直接使用接口。另一方面,_blockReaderFactory
是一个接口,因此很容易模拟。我怎么能模仿这么复杂的对象呢。我正在使用Rhino Mocks和Microsoft Unit Testing Framework。有人有什么想法吗?
public void ReadGeneral(FsFileGroupFile a_file, FileItemData a_fileItemData)
{
try
{
var blockReader = _blockReaderFactory.Create(a_file.File.FullName, "CabinetData/StartData");
var version = blockReader.ReadVersion();
var name = blockReader.ReadString();
var type = blockReader.ReadString();
var defaultHeight = blockReader.ReadDouble();
var defaultWidth = blockReader.ReadDouble();
var defaultDepth = blockReader.ReadDouble();
a_fileItemData.Name = name;
a_fileItemData.DefaultWidth = defaultWidth * 100.0;
a_fileItemData.DefaultHeight = defaultHeight * 100.0;
a_fileItemData.DefaultDepth = defaultDepth * 100.0;
}
catch (Exception ex)
{
throw new IOException("General data could not be read from block data.", ex);
}
}
答案 0 :(得分:1)
您似乎只使用a_file
来获取文件名。那么为什么不创建一个接口FilenameSupplier
(或类似的),并编写一个实现它的包装器?
Java代码示例(在问题之前添加标记为C#...):
interface FilenameSupplier {
String getName();
}
public void ReadGeneral(FilenameSupplier a_file, FileItemData a_fileItemData) {
...
a_file.getName();
...
}
class ConcreteSupplier implements FilenameSupplier {
private final FsFileGroupFile file;
public ConcreteSupplier(FsFileGroupFile file) { this.file = file; }
String getName() { return a_file.File.FullName; }
}
答案 1 :(得分:0)
您应该从FsFileGroupFile
中提取一些接口并将其传递给构造函数参数。
然后你可以轻松地用你喜欢的框架模拟这个界面,在你的情况下使用Rhino Mocks。
如果不合适,你应该构建你的FsFileGroupFile
,并且在复杂的构造函数中传递参数时可能会使用模拟。
似乎没有其他选择,除非你可以在这里审查你的设计。如果课程很难测试,那么这可能是设计不佳的标志。
答案 2 :(得分:0)
当我不得不在测试中创建复杂的对象时,我使用了Test Data Builder Pattern。举个例子,我们假设您有五个值传递给构造函数:
public FsFileGroupFile(string firstProperty, string secondProperty,
string thirdProperty, string fourthProperty, string fifthProperty)
{
// constructor logic goes here
}
然后将在单元测试项目中使用测试构建器类进行包装:
public class FsFileGroupFileBuilder
{
public string FirstProperty { get; set; }
public string SecondProperty { get; set; }
public string ThirdProperty { get; set; }
public string FourthProperty { get; set; }
public string FifthProperty { get; set; }
public FsFileGroupFile Build()
{
return new FsFileGroupFile(FirstProperty, SecondProperty, ThirdProperty,
FourthProperty, FifthProperty);
}
}
现在,您只能为您关注的属性指定值,并以这种方式构建对象:
// in your test setup use this to initial to a default/valid state
var fsFileGroupBuilder = new fsFileGroupBuilder
{
FirstProperty = "Default",
SecondProperty = "Default",
ThirdProperty = "Default",
FourthProperty = "Default",
FifthProperty = "Default"
}
注意:Rhino Mocks可能会为你设置这些默认值,但我没有亲自使用它,所以我不确定。
// Override the properties in each test
fsFileGroupBuilder.ThirdProperty = "Value needed for unit test."
// create
var fileItemData = new FileItemData();
ReadGeneral(fsFileGroupBuilder.Build(), fileItemData);
还有其他开源库可以帮助生成测试数据,例如NBuilder,这些数据在过去对我有用。
这里的要点是复杂的构造函数可以使用构建器抽象出来,这样您就可以专注于测试业务逻辑,而不是在每次测试中都满足构造函数。