繁体   English   中英

如何测试委托方法

[英]How to test a delegated method

我在类中有一个简单的方法,负责在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方法已正确注册以在创建文件时侦听“路径”。

如何执行项目2的单元测试?

非常感谢

在事件上注册回调仅是填充变量。 或多或少将回调添加到回调列表中。 我通常不会验证诸如列表填充之类的偶然事物,除非数据填充是类的整个要点(例如,如果类表示自定义数据结构)。

您可以改为在修改指定文件时验证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
}

如果您有权访问FileSystemWatcher则可以对其进行设置,以便模拟Created事件的触发。 但是我怀疑并非如此,这意味着您到了真正的“单元测试”并非易事的地步。

您可以尝试使用诸如TypeMock或Moles之类的隔离器来模拟Created事件的触发。 但是最简单的方法可能是实际编写一个在给定路径上创建文件的测试,并确保在发生这种情况时调用ProcessInput方法。

因为您还没有显示ProcessInput本身的定义或任何其他代码,所以我不知道确保调用它的最佳方法。

您可以将方法分为两种:第一种方法仅实例化,配置并返回FileSystemWatcher的实例。 然后,您可以轻松地对返回的结果对象进行测试。 第二种方法可以将其作为参数,并仅在其上启用上升事件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM