等待IO的可重用测试代码

本文关键字:测试 代码 IO 等待 | 更新日期: 2023-09-27 18:07:52

我正在尝试在WCF暴露的方法/服务上使用async/await。一切工作正常,但我想模拟服务方法实际等待IO,以便服务调用将注册到IO完成端口,并将线程放回线程池。

澄清一下,我只是在做实验,以确认IO完成端口的使用,并更好地理解实际发生的机制。

所以,例如,我的测试服务目前看起来像这样:

[ServiceContract]
public interface IHelloWorldService
{
    [OperationContract]
    Task<string> SayHello(string firstName, string lastName);
}

public class HelloWorldService : IHelloWorldService
{
    public async Task<string> SayHello(string firstName, string lastName)
    {
        string str = string.Format("Hello {0} {1}", firstName, lastName);
        return await Task.Factory.StartNew(() => str);
    }
}

我想在SayHello()中做一些事情来导致代码等待一些IO,理想情况下,当我想模拟等待IO时,我可以复制/粘贴通常使用的代码模式。

通常使用thread . sleep()来模拟长时间运行的任务,但我很确定这会使线程池线程休眠,而不会触发IO完成端口的使用。

等待IO的可重用测试代码

当我想模拟等待IO时,我可以复制/粘贴通常使用的代码模式。

通常使用Thread.Sleep()来模拟长时间运行的任务

正如在评论中已经提到的,await Task.Delay(..)Thread.Sleep(..)的异步等价物。它通常用于表示"未指定的异步操作"。

public async Task<string> SayHello(string firstName, string lastName)
{
    await Task.Delay(TimeSpan.FromSeconds(2));
    return string.Format("Hello {0} {1}", firstName, lastName);
}
但是,如果这是一个测试/模拟存根,那么您可能不希望延迟实际的时间。异步测试存根通常与Task.FromResult(或Task.FromExceptionTask.FromCancelled)同步实现:
public Task<string> SayHello(string firstName, string lastName)
{
    return Task.FromResult(string.Format("Hello {0} {1}", firstName, lastName));
}

但是听起来你想要强制异步。请注意,在单元测试中很少需要这样做,但它确实不时出现。要在不占用宝贵时间的情况下强制异步,请使用Task.Yield:

public async Task<string> SayHello(string firstName, string lastName)
{
    await Task.Yield();
    return string.Format("Hello {0} {1}", firstName, lastName);
}