我目前的代码如下:
public class SerializeFileHandler
{
public void WriteListToFile(MyProject myProject, string filePath)
{
FileStream outFile;
BinaryFormatter bFormatter = new BinaryFormatter();
outFile = new FileStream(filePath, FileMode.Create, FileAccess.Write);
bFormatter.Serialize(outFile, myProject);
// Close file
outFile.Close();
}
public MyProject ReadListFromFile(String filePath)
{
FileStream inFile;
BinaryFormatter bFormatter = new BinaryFormatter();
MyProject myProject = new MyProject();
// Open file for input
inFile = new FileStream(filePath, FileMode.Open, FileAccess.Read);
// Obtain objects from file via serialization
myProject = (MyProject)bFormatter.Deserialize(inFile);
inFile.Close();
return myProject;
}
}
要保存数据文件,我使用public const string myProjectFile = "myproject.dat";
,然后当用户单击“保存”按钮时,将任何新数据保存到文件中。当然,我会在括号中使用参数serializeFileHandler.WriteListToFile();
。
我想要做的是编写单元测试或多个测试,以便在将数据文件读入应用程序方面测试功能。目前,程序加载时会自动加载数据文件(只需ReadListFromFile
上的serializeFileHandler
。
我已经在Visual Studio中使用测试向导创建了测试,但我不确定如何构建测试来自动测试文件读取功能。任何帮助将不胜感激。
答案 0 :(得分:0)
如果是我,我会有一个ReadListFromStream方法,然后我将测试流注入到chcek中,myProject已正确加载。
从文件中测试 我存根ReadListFromStream,只需确保ReadListFromFile调用它。
答案 1 :(得分:0)
SerializeFileHandler
目前的问题是它依赖FileStream
,后者又将其与文件系统的读取联系起来;为了当前为它编写测试,我们实际上需要与文件系统进行交互。
我们可以通过引入测试接缝来打破对文件系统的依赖,这将允许我们模拟/存根/伪造FileStream
的行为。在生产系统中,我们会通过SerializeFileHandler
一个FileStream
来使用,但在单元测试中,我们会传递一些符合FileStream
SerializeFileHandler
接口的内容。 1}}正在使用,但允许我们控制行为以进行测试。
首先,我们可以为与文件系统交互的流引入接口
public interface IFileStreamSource
{
Stream Open(string path, FileMode mode, FileAccess access, FileShare share);
}
让SerializeFileHandler
依赖于此
public class SerializeFileHandler
{
private readonly IFileStreamSource _source;
public SerializeFileHandler(IFileStreamSource source)
{
_source = source;
}
public void WriteListToFile(MyProject myProject, string filePath)
{
using (var stream = _source.Open(filePath, FileMode.Create, FileAccess.Write)
{
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, myProject);
}
}
public MyProject ReadListFromFile(String filePath)
{
MyProject myProject = null;
using (var stream = _source.Open(filePath, FileMode.Open, FileAccess.Read))
{
BinaryFormatter bFormatter = new BinaryFormatter();
// Obtain objects from file via serialization
myProject = (MyProject)bFormatter.Deserialize(stream);
}
return myProject;
}
}
现在,您可以使用模拟库(例如Moq)在单元测试中创建Mock<IFileStreamSource>()
,可能会返回MemoryStream
,并设置Open()
时间的预期叫做。
在您的生产代码中,您可能决定为SerializeFileHandler
创建一个无参数构造函数,该构造函数将IFileStreamSource
的实例传递给带有IFileStreamSource
的构造函数,该构造函数将返回一个实例调用FileStream
时Open()
的{{1}}(la "Poor Man's Dependency Injection"),或者您可能已经在使用IoC / Dependency Injection容器,在这种情况下,您只需为{IFileStreamSource
注册组件{1}}服务。
查看当前的代码,我可以看到一些未在ReadListFromFile
中处理的情况,例如文件是否存在或文件是否存在但无法反序列化为{{1}的实例}}。您可能希望为案例编写测试并相应地更新代码:)
答案 2 :(得分:0)
如果您需要测试与文件系统交互,可以像其他建议一样创建模拟文件系统包装,或者创建测试可以使用的隔离文件系统。我更喜欢第二种方法,因为测试与现实更相似。
在运行测试之前,设置一个包含测试所需文件的文件夹。然后让测试中的代码访问该文件夹,而不是实际代码访问的文件夹。这样,您可以读取文件,测试代码在缺少文件时的工作方式,以及测试文件创建。