Reusable test code that waits for IO

旧城冷巷雨未停 提交于 2019-12-23 16:34:11

问题


I'm experimenting with using async/await on WCF exposed methods/services. Everything works fine but I'd like to simulate the service method actually waiting for IO so that the service call will be registered with an IO completion port, and the thread put back into the thread pool.

To clarify, I'm just experimenting to confirm usage of IO completion ports and to get a better understanding of the mechanics of what's actually going on.

So e.g. my test service currently looks like this:

[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);
    }
}

I'd like to do something in SayHello() to cause that code to wait for some IO, ideally a code pattern I can copy/paste to use generally when I want to simulate waiting for IO.

Typically Thread.Sleep() is used to simulate a long running task, but I'm pretty sure that will put the thread pool thread to sleep and not trigger usage of an IO completion port .


回答1:


a code pattern I can copy/paste to use generally when I want to simulate waiting for IO.

Typically Thread.Sleep() is used to simulate a long running task

As already mentioned in the comments, await Task.Delay(..) is the asynchronous equivalent of Thread.Sleep(..). It's commonly used to represent an "unspecified asynchronous operation".

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

However, if this is a test/mock stub, then you probably don't want to delay for a real amount of time. Asynchronous test stubs are generally implemented synchronously with Task.FromResult (or Task.FromException or Task.FromCancelled):

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

But it sounds like you want to force asynchrony. Note that needing to do this in a unit test is rare, but it does come up from time to time. To force asynchrony without taking up valuable time, use Task.Yield:

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


来源:https://stackoverflow.com/questions/32008662/reusable-test-code-that-waits-for-io

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!