2012-09-11 58 views
0

我有一个使用StreamWriter写入文件的类。嘲笑StreamWriter /确定何时模拟

public void CreateLog(string errorLogFilePath, StringBuilder errorLogBuilder, string errorMessage) 
{ 
    using (StreamWriter sw = new StreamWriter(errorLogFilePath, true) 
    { 
     errorLogBuilder.Apend("An error was discovered."); 
     //.... 
     sw.Write(errorLogBuilder.ToString()); 
    } 
} 

[问题]

1:是否有可能检查.WRITE()方法被调用?

2:我是否需要在StreamWriter内部包装MemoryStream才能测试它,而无需实际访问硬盘驱动器。一个StreamWriters构造函数接受一个流,但它声明以下内容+ UTF-8编码是否会影响这个?

使用UTF-8编码和默认缓冲区大小为指定流初始化StreamWriter类的新实例。

3:如何确定一个类是否实际访问hd并因此需要被模拟? (对不起,如果这最后一个问题听起来很愚蠢,但我真的有点困惑于此)。

回答

3

让方法写入TextWriter而不是StreamWriter。然后通过传递一个模拟TextWriter来测试该方法。在“真实”代码中,当然,您将传入使用new StreamWriter(errorLogFilePath, true)创建的StreamWriter。

我们得到以下问题的答案:

  1. 没有
  2. 你一般不能确定,如果没有反编译其代码。

更详细一点:

重构方法为两种方法:

public void CreateLog(string errorLogFilePath, StringBuilder errorLogBuilder, string errorMessage) 
{ 
    using (StreamWriter sw = new StreamWriter(errorLogFilePath, true) 
    { 
     CreateLog(sw, errorLogBuilder, errorMessage); 
    } 
} 

public void CreateLog(TextWriter writer, StringBuilder errorLogBuilder, string errorMessage) 
{ 
    errorLogBuilder.Apend("An error was discovered."); 
    //.... 
    writer.Write(errorLogBuilder.ToString()); 
} 

测试,以确保它调用与适当构造的StreamWriter的第二种方法中,第一种方法。测试第二种方法以确保它在传递的TextWriter上调用Write,并带有适当的参数。现在你已经提取了硬盘上的依赖关系。您的测试不使用硬盘,但您正在测试所有内容。

+0

感谢您的回复。关于(3),我指的是MemoryStream,StreamReader,StreamWriter等。你如何知道哪一个实际访问HD?大约一个月前,我问了一个类似的问题,Jon Skeet说我可以在StreamReader中包装一个memoryStream。为什么我不能在这里做同样的事情? –

+0

@HansRudel你确实可以在这里做同样的事情(顺便提一下,StreamWriter的构造函数可以让你提供一个流*和*指定编码),但是我发现这种方法更简单。使用内存流创建StreamWriter将允许您在没有模拟框架的情况下编写测试,但是您使用了'moq'标记,那么为什么不只是模拟抽象类呢? – phoog

+0

@HansRudel我忘记了地址(3)。访问HD的类是FileStream。当您将文件路径而不是流传递给StreamWriter构造函数时,StreamWriter会创建一个FileStream。如果你有一个StreamWriter并想知道它正在写什么(文件,内存,其他),你应该能够通过检查它的BaseStream属性来确定它。 – phoog

1

一般来说,你可以:

使用以及测试日志库(如NLOG,MS记录应用程序块),省得你深化发展和维护自己。

将您的日志逻辑(或调用消息框的代码,打开文件对话框等)重构为带有其接口的服务。通过这种方式,您可以拆分测试策略:

  • 测试loggin服务的使用者时:模拟日志记录界面以确保调用日志方法。这将确保日志记录服务的消费者在测试日志记录服务实现时正确调用日志记录服务
  • ,只需确保预期的输出匹配给定的输入:如果要将“FOO”写入条形图。登录,有效地叫

IE:

// arrrange 
File.Delete("bar.log") 

// act 
CreateLog("bar.log", errorLogBuilder, "FOO") 

// assert 
Assert.IsTrue(File.Exists("bar.log")) 
Assert.IsTrue(File.ReadAllLines("bar.log").First() == "FOO") 

点是确保该组件被调用,通过嘲讽来完成。 然后您可以检查组件是否按预期工作。