Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to unit test an asynchronous method?

I can't seem to find a .NET answer to this problem, which I would have thought would be fairly common.
What is the best pattern for unit testing an asynchronous method?

Obviously I need to call the method and then see if the callback fires, but is there a better way than simply sleeping for a bit and then checking for a flag that is set by the callback? Managing the flags gets a bit messy where there are multiple tests running.

like image 967
Kid Kaneda Avatar asked Dec 30 '08 15:12

Kid Kaneda


People also ask

How do you test asynchronous?

To test asynchronous code, we use the XCTestExpectation class and wait for the expected outcome. The workflow is to create an expectation, and then when the asynchronous task completes successfully, we fulfil that expectation. We will wait for a specific amount of time for the expectation to be fulfilled.

Can unit tests be async?

Async unit tests that return Task have none of the problems of async unit tests that return void. Async unit tests that return Task enjoy wide support from almost all unit test frameworks.


1 Answers

I typically use an anonymous delegate and a waithandle. FOr example I have a function in my presenter called SetRemoteTableName. When the name is set, it also raises an event. I want to test that event, which is raised asynchronously. The test looks like this:

[TestMethod]
[WorkItem(244)]
[Description("Ensures calling SetRemoteTableName with a valid name works 
              AND raises the RemoteTableNameChange event")]
public void SetRemoteTableNamePositive()
{
  string expected = "TestRemoteTableName";
  string actual = string.Empty;

  AutoResetEvent are = new AutoResetEvent(false);
  SQLCECollectorPresenter presenter = new SQLCECollectorPresenter();
  presenter.RemoteTableNameChange += new EventHandler<GenericEventArg<string>>(
    delegate(object o, GenericEventArg<string> a)
    {
      actual = a.Value;
      are.Set();
    });

  presenter.SetRemoteTableName(expected);
  Assert.IsTrue(are.WaitOne(1000, false), "Event never fired");
  Assert.AreEqual(actual, expected);
}
like image 191
ctacke Avatar answered Oct 12 '22 19:10

ctacke