Note that there are some explanatory texts on larger screens.

plurals
  1. POHow do I unit test a method containing an asynchronous call?
    text
    copied!<p>I have a method that contains an asynchronous call like this:</p> <pre><code>public void MyMethod() { ... (new Action&lt;string&gt;(worker.DoWork)).BeginInvoke(myString, null, null); ... } </code></pre> <p>I'm using Unity and creating mock objects is not a problem, but how can I test that DoWork is called without worrying about race conditions?</p> <p>A <a href="https://stackoverflow.com/questions/400552/what-is-the-best-way-to-unit-test-an-asynchronous-method">previous question</a> offers a solution, but it seems to me that wait-handles is a hack (the race condition is still there, although it should be virtually impossible to raise).</p> <hr> <p>EDIT: Okay, I thought I could ask this question in a very general manner, but it seems I have to elaborate further on the problem:</p> <p>I want to create a test for the above mentioned MyMethod, so I do something like this:</p> <pre><code>[TestMethod] public void TestMyMethod() { ...setup... MockWorker worker = new MockWorker(); MyObject myObj = new MyObject(worker); ...assert preconditions... myObj.MyMethod(); ...assert postconditions... } </code></pre> <p>The naïve approach would be to create a MockWorker() that simply sets a flag when DoWork has been called, and test that flag in the postconditions. This would of course lead to a race condition, where the postconditions are checked before the flag is set in the MockWorker.</p> <p>The more correct approach (which I'll probably end up using) is using a wait-handle:</p> <pre><code>class MockWorker : Worker { public AutoResetEvent AutoResetEvent = new AutoResetEvent(); public override void DoWork(string arg) { AutoResetEvent.Set(); } } </code></pre> <p>...and use the following assertion:</p> <pre><code>Assert.IsTrue(worker.AutoResetEvent.WaitOne(1000, false)); </code></pre> <p>This is using a semaphore-like approach, which is fine... but in <em>theory</em> the following could happen:</p> <ol> <li>BeginInvoke is called on my DoWork delegate</li> <li>For some reason neither the main-thread or the DoWork-thread is given execution time for 1000ms.</li> <li>The main-thread is given execution time, and because of the timeout the assertion fails, even though the DoWork thread is yet to be executed.</li> </ol> <p>Have I misunderstood how AutoResetEvent works? Am I just being too paranoid, or is there a clever solution to this problem?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload