2014-03-04 51 views
0

我目前拥有的代码如下:单元测试文件阅读功能

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();当然在括号中的参数。

我想要做的是编写一个单元测试或多个测试,如果需要测试功能在读取数据文件到应用程序的方面。目前,数据文件会自动加载时在程序加载(只是不上serializeFileHandler

我一直在使用Visual Studio中测试向导创建的测试ReadListFromFile,但我不知道我怎么会构建测试自动化的文件阅读功能测试。任何帮助,将不胜感激。

+0

这是有点不清楚你试过什么,你的问题是什么,请尝试解决这个问题。 –

回答

0

如果是我,我就会有一个ReadListFromStream方法,然后我会注入测试流chcek是myProject的正确装起来。

要从文件 测试,我会存根ReadListFromStream,并且确保ReadListFromFile调用它。

+0

你有没有一个代码可能看起来像这样的例子?在处理C#中的序列化文件方面,我相对较新,所以它对我来说是很新的。 – user3380790

+0

打开它时,它看起来就像是该文件。看看它,通过集成测试可能会更好。创建一个东西,调用WriteToFile。用该文件中的ReadFromFile创建另一个文件,然后比较这两个实例。你在这里测试的是文件系统,这是一个价值很低的序列化标记,很少看到。 –

+0

我只是有点糊涂,因为我觉得如何在我的代码中实际实现测试时感到非常困惑。 – user3380790

0

SerializeFileHandler目前存在的问题是它对FileStream有依赖关系,而这又依赖于从文件系统读取;为了为它编写一个当前的测试,我们实际上需要与文件系统进行交互。

我们可以通过引入测试接缝来打破对文件系统的依赖关系,这将允许我们模拟/存根/伪造FileStream的行为。在生产系统中,我们将通过SerializeFileHandler a FileStream来处理,但在单元测试中,我们会传递一些符合FileStream的接口SerializeFileHandler正在使用的接口,但允许我们控制用于测试目的的行为。

首先,我们可以引入一个接口,用于与文件系统

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构造,当Open()被称为将返回的FileStream一个实例(一拉"Poor Man's Dependency Injection") ,或者您可能已经在使用IoC/Dependency Injection容器,在这种情况下,您只需为IFileStreamSource服务注册组件。

查看目前的代码,我可以看到一些在ReadListFromFile中未处理的情况,例如文件不存在或文件确实存在但无法反序列化为MyProject的实例。您可能需要编写测试案例并相应地更新代码:)

0

如果您需要测试与文件系统交互,您可以按照其他建议创建模拟文件系统包装,或者创建一个独立的文件系统测试可以使用。我更喜欢第二种方法,因为测试更接近现实。

在测试运行之前,建立一个包含测试需要的所有文件的文件夹。然后让测试中的代码访问该文件夹,而不是实际代码访问的文件夹。这样,您可以阅读文件,测试代码如何工作(如果文件丢失),并测试文件创建。