Reusable test code awaiting I / O

I am experimenting with using async / await on WCF exposed methods / services. Everything works fine, but I would like to simulate a service method waiting for I / O so that the service call is registered with the I / O completion port and the thread is pushed back to the thread pool.

To clarify, I'm just experimenting to validate the use of the I / O ports and get a better understanding of what is going on.

So, for example, 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 would like to do something in SayHello () to make this code wait for some I / O, ideally a code pattern that I can copy / paste to use when I want to simulate waiting for I / O.

Typically Thread.Sleep () is used to simulate a long running task, but I'm pretty sure this will cause the thread pool thread to sleep and not start using the I / O completion port.

+2


source to share


1 answer


a code template that I can copy / paste to use in general when I want to simulate waiting for I / O.

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

As mentioned in the comments, await Task.Delay(..)

is the asynchronous equivalent Thread.Sleep(..)

. It is commonly used to represent "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 linger for a real amount of time. Asynchronous test stubs are usually implemented in sync 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 looks like you want to force async. Note that this needs to be done in a unit test, but it comes up from time to time. To force async without wasting precious time, use Task.Yield

:

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

      

+2


source







All Articles