我在一个类中有一个简单的方法,它负责在appconfig.xml中给定某个路径注册FileSystemWatcher:
public void ListenPath(string path){
//path validation code
//...
FileSystemWatcher objFileWatcher = new FileSystemWatcher();
objFileWatcher.Path = path;
objFileWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
objFileWatcher.Filter = "*.txt";
objFileWatcher.Created += new FileSystemEventHandler(ProcessInput);
objFileWatcher.EnableRaisingEvents = true;
}
在我的单元测试中,我必须声明:
1)提供错误或空路径应该引发PathNotFoundException
2)正确注册了ProcessInput方法,以便在创建文件时监听“path”。
如何执行第2项的单元测试?
非常感谢
答案 0 :(得分:1)
在事件上注册回调只是填充变量。它或多或少地将回调添加到回调列表中。我通常不会验证附带的东西,例如列表的填充,除非数据填充是类的整个点(就像类表示自定义数据结构一样)。
您可以改为在修改指定文件时验证是否调用了ProcessInput
。有几种方法可以解决这个问题:
ProcessInput
的副作用,例如它填充了程序中的其他结构或属性ProcessInput
方法分离到另一个类或接口。引用此类型作为ListPath
的参数,或类的构造函数。然后模拟那种类型模拟对象示例:
public interface IInputProcessor
{
void ProcessInput(Object sender, FileSystemEventArgs e);
}
public class ClassUnderTest
{
public ClassUnderTest(IInputProcessor inputProcessor)
{
this.inputProcessor = inputProcessor;
}
public void ListenPath(string path){
// Your existing code ...
objFileWatcher.Created +=
new FileSystemEventHandler(inputProcessor.ProcessInput);
// ...
}
private IInputProcessor inputProcessor;
}
public class MockInputParser : IInputProcessor
{
public MockInputParser()
{
this.Calls = new List<ProcessInputCall>();
}
public void ProcessInput(Object sender, FileSystemEventArgs args)
{
Calls.Add(new ProcessInputCall() { Sender = sender, Args = args });
}
public List<ProcessInputCall> Calls { get; set; }
}
public class ProcessInputCall
{
public Object Sender;
public FileSystemEventArgs Args;
}
[Test]
public void Test()
{
const string somePath = "SomePath.txt";
var mockInputParser = new MockInputParser();
var classUnderTest = new ClassUnderTest(mockInputParser);
classUnderTest.ListenPath(somePath);
// Todo: Write to file at "somePath"
Assert.AreEqual(1, mockInputParser.Calls.Count);
// Todo: Assert other args
}
答案 1 :(得分:0)
如果FileSystemWatcher
是您有权访问的内容,则可以对其进行设置,以便模拟Created
事件的触发。但我怀疑它不是,这意味着你已经达到了真正的“单元测试”并不容易的地步。
您可以尝试使用像TypeMock或Moles这样的隔离器来模拟Created
事件的触发。但最简单的事情可能是实际编写一个在给定路径上创建文件的测试,并确保在发生这种情况时调用ProcessInput方法。
因为您没有在ProcessInput本身周围显示定义或任何其他代码,所以我不知道确保调用它的最佳方法。
答案 2 :(得分:0)
您可以将方法拆分为两个:第一个方法只是实例化,配置并返回FileSystemWatcher的一个实例。然后,您可以轻松地测试返回的结果对象。第二种方法可以将其作为参数,并简单地在其上启用上升事件。