{"id":1356,"date":"2010-11-11T21:40:35","date_gmt":"2010-11-11T20:40:35","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=1356"},"modified":"2021-07-03T13:28:03","modified_gmt":"2021-07-03T12:28:03","slug":"c-5-0-async-feature-unit-testing-part-iii-avoid-void","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2010\/11\/c-5-0-async-feature-unit-testing-part-iii-avoid-void\/","title":{"rendered":"C# 5.0 Async-Feature: Unit Testing Part III, Avoid Void."},"content":{"rendered":"<div id=\"attachment_1363\" style=\"width: 310px\" class=\"wp-caption alignright\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/csharp-learns-from-fsharp.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1363\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/csharp-learns-from-fsharp-300x174.png\" alt=\"C# Learns From F#\" title=\"csharp-learns-from-fsharp\" class=\"size-medium wp-image-1363\" width=\"300\" height=\"174\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/csharp-learns-from-fsharp-300x174.png 300w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/csharp-learns-from-fsharp.png 800w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1363\" class=\"wp-caption-text\">C# Learns From F#<\/p><\/div>\n<p><span style=\"color: #ff0000; font-size: medium;\">Disclaimer: <\/span><span style=\"font-size: medium;\">This post is based on the C# 5.0 CTP. Everything described here is subject to future changes. <\/span><\/p>\n<p><a href=\"?p=1325\">Last time I demonstrated<\/a> that the synchronization context is also relevant for unit testing and that you might need to setup one in your tests. This time we\u2019re going to explore what we can do when a asynchronous method returns void instead of a task.<\/p>\n<p>Once again we write some code for our imaginary desktop application. This time we test a method which sends some stuff to costumers. When the package is sent an event is raised. First the synchronous version. It\u2019s straight forward, we package the goods and then send it. When we\u2019re done we fire the event.<\/p>\n<p>The Implementation <script src=\"https:\/\/gist.github.com\/673065.js?file=ComplexBusinessOperations-1.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">public event Action GoodsArrived;\n\npublic void SendGoodsToCostumers(string theGoods)\n{\n    var package = PreparePackage(theGoods);\n    SendPackage(package);\n    GoodsArrived();\n}\n\nprivate string SendPackage(string package)\n{\n    \/\/ This operation takes a while\n    Thread.Sleep(50);\n    return &quot;Send: &quot; + package;\n            \n}\n\nprivate string PreparePackage(string theGoods)\n{\n    \/\/ This operation takes a while\n    Thread.Sleep(50);\n    return &quot;Wrapped: &quot; + theGoods;\n}<\/code><\/pre><\/noscript><\/p>\n<p>The Test <script src=\"https:\/\/gist.github.com\/673065.js?file=ComplexBusinessOperationsTest-1.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">[Test]\npublic void SendGoodsToCostumers()\n{\n    var toTest = new ComplexBusinessOperations();\n\n    var wasSent = false;\n    toTest.GoodsArrived += () =&gt; wasSent = true;\n    toTest.SendGoodsToCostumers(&quot;A Nice Toy&quot;);\n    Assert.IsTrue(wasSent);\n}<\/code><\/pre><\/noscript><\/p>\n<p>As expected everything runs smooth. Now we\u2019re turning the method into an asynchronous implementation <script src=\"https:\/\/gist.github.com\/673065.js?file=ComplexBusinessOperations-2.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">public event Action GoodsArrived;\n\npublic async void SendGoodsToCostumersAsync(string theGoods)\n{\n    var package = await PreparePackageAsync(theGoods);\n    var sentPackage = await SendPackageAsync(package);\n    GoodsArrived();\n}\n\nprivate Task&lt;string&gt; SendPackageAsync(string package)\n{\n    \/\/ Remember, this is just a simulation\n    \/\/ Usually you would use some other async API here\n    return TaskEx.Run(() =&gt;\n                            {\n                                \/\/ This operation takes a while\n                                Thread.Sleep(50);\n                                return &quot;Send: &quot; + package;\n                            });\n}\n\nprivate Task&lt;string&gt; PreparePackageAsync(string theGoods)\n{\n    \/\/ Remember, this is just a simulation\n    \/\/ Usually you would use some other async API here\n    return TaskEx.Run(() =&gt;\n                            {\n                                \/\/ This operation takes a while\n                                Thread.Sleep(50);\n                                return &quot;Wrapped:: &quot; + theGoods;\n                            });\n}<\/code><\/pre><\/noscript><\/p>\n<p>As soon as we try to update the test-method we\u2019re facing a problem. We cannot wait for a void-result. This means there\u2019s no way to wait for the completion of the task. Well the easiest thing to do is to change the result to return a task. This allows us to wait in the test.<\/p>\n<p>Returning a Task <script src=\"https:\/\/gist.github.com\/673065.js?file=ComplexBusinessOperations-3.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">\/\/ Return a Taks instead of void to make testing easier\npublic async Task SendGoodsToCostumersAsync(string theGoods)\n{\n    var package = await PreparePackageAsync(theGoods);\n    var sentPackage = await SendPackageAsync(package);\n    GoodsArrived();\n}<\/code><\/pre><\/noscript><\/p>\n<p>The Test <script src=\"https:\/\/gist.github.com\/673065.js?file=ComplexBusinessOperationsTest-2.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">[Test]\npublic void SendGoodsToCostumers()\n{\n    var toTest = new ComplexBusinessOperations();\n\n    var wasSent = false;\n    toTest.GoodsArrived += () =&gt; wasSent = true;\n    toTest.SendGoodsToCostumersAsync(&quot;A Nice Toy&quot;).Wait();\n    Assert.IsTrue(wasSent);\n}<\/code><\/pre><\/noscript><\/p>\n<h2>In The Case Of Void<\/h2>\n<p>Now we\u2019ve seen that when we return a task instead of void we can make our testing-life much easier. But what if that&#8217;s not possible? For example because we don\u2019t want to break the API. Or if it\u2019s a library call which we cannot change. Then this gets a little more tricky. When the method returns void we cannot wait for the task to complete. A ugly work around would be to just use Thread.Sleep for a certain time an hope that everything completes meanwhile. However this is a brittle method and prolongs our test unnecessary. What can we do instead? Remember the <a href=\"?p=1325\">previous post<\/a> where we used a special synchronization-context which allowed us to wait on a task? Well does this really have to be a task? I mean we can wait for other things, right?<\/p>\n<p>So the basic idea is to extend our test synchronization context to provide a special wait-method. And while we\u2019re waiting we process other messages. This is actually only a small extension <a href=\"?p=1325\">to our existing code<\/a><script src=\"https:\/\/gist.github.com\/673065.js?file=Awaiter.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">public class Awaiter\n{\n    private readonly MyPrimitiveSynchronisationContext syncContext;\n\n    internal Awaiter(MyPrimitiveSynchronisationContext syncContext)\n    {\n        this.syncContext = syncContext;\n    }\n\n    public void WaitFor(IAsyncResult toWaitOn)\n    {\n        WaitFor(() =&gt; toWaitOn.IsCompleted);      \n    }\n    \/\/ Our new wait method which can wait for anything\n    \/\/ Continues when the condition is true\n    public void WaitFor(Func&lt;bool&gt; toWaitOn)\n    {\n        while (!toWaitOn())\n        {\n            syncContext.RunOneRound();\n        }\n    }\n}<\/code><\/pre><\/noscript><\/p>\n<p>Now we can use this in our test. We run our test-code in the test synchronization context. Then we wait until the condition is fulfilled and finally continue <script src=\"https:\/\/gist.github.com\/673065.js?file=ComplexBusinessOperationsTest-3.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">[Test]\npublic void SendGoodsToCostumers()\n{\n    TestSyncContext.Run((awaiter)=&gt;\n    {\n        var toTest = new ComplexBusinessOperations();\n\n        var wasSent = false;\n        toTest.GoodsArrived += () =&gt; wasSent = true;\n        toTest.SendGoodsToCostumersAsync(&quot;A Nice Toy&quot;);\n        awaiter.WaitFor(()=&gt;wasSent);\n        Assert.IsTrue(wasSent);\n                                \n    });\n}<\/code><\/pre><\/noscript><\/p>\n<p>You\u2019ve probably noticed that this test will run forever instead of failing. Unfortunately we cannot fix that. The only thing we can do is to implement some kind of timeout and maybe use a reasonable default. But you can implement that without my help ;).<\/p>\n<h2>Conclusion<\/h2>\n<p>In this post I demonstrated that you should always return a task in an asynchronous API instead of void. This allows us to easily test the code and makes it more flexible. In the cases where we have to deal with asynchronous code which doesn\u2019t return a task we have to get creative with special wait conditions.<\/p>\n<p>Now I\u2019ve finished with my little tour through Unit testing with the new asynchronous features. This post series is by no means a complete guide. It&#8217;s here to get an impression where the difficulties lie. I think when the async feature ships some knowledge and patterns have already emerged. And maybe we all should take a looks at F#. Because F# has had asynchronous workflows for quite a while. And don\u2019t forget do download and experiment with the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/vstudio\/async.aspx\">Async CTP<\/a> yourself.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Disclaimer: This post is based on the C# 5.0 CTP. Everything described here is subject to future changes. Last time I demonstrated that the synchronization context is also relevant for&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[126],"tags":[21,200,24,199],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1356"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=1356"}],"version-history":[{"count":15,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1356\/revisions"}],"predecessor-version":[{"id":3879,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1356\/revisions\/3879"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=1356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=1356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=1356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}