{"id":1325,"date":"2010-11-08T22:42:11","date_gmt":"2010-11-08T21:42:11","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=1325"},"modified":"2021-07-03T13:28:07","modified_gmt":"2021-07-03T12:28:07","slug":"c-5-0-async-feature-unit-testing-part-ii-synchronization-context-again","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2010\/11\/c-5-0-async-feature-unit-testing-part-ii-synchronization-context-again\/","title":{"rendered":"C# 5.0 Async-Feature: Unit Testing Part II, Synchronization-Context Again?"},"content":{"rendered":"<div id=\"attachment_1332\" style=\"width: 303px\" class=\"wp-caption alignright\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/unit-test-2-sync-issues.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1332\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/unit-test-2-sync-issues-293x300.png\" alt=\"Getting Synchronisation Right Is Hard\" title=\"unit-test-2-sync-issues\" class=\"size-medium wp-image-1332\" width=\"293\" height=\"300\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/unit-test-2-sync-issues-293x300.png 293w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/unit-test-2-sync-issues.png 600w\" sizes=\"(max-width: 293px) 100vw, 293px\" \/><\/a><p id=\"caption-attachment-1332\" class=\"wp-caption-text\">Getting Synchronisation Right Is Hard<\/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=1289\">Last time we explored<\/a> some implications of the C# asynchronous operations for unit tests. We noticed that we need to orchestrate tests to honor the asynchronous nature of our code. This time we take a look at another pit fall. Again this example assumes that we\u2019re developing a small desktop application.<\/p>\n<p>Let\u2019s start: This time our business operation sums up a value, let\u2019s say it sums up money. Since it\u2019s hard to earn a Dollar\/Euro\/Swiss Franc it takes a while. And to earn more we do this money earning process twice. Our synchronous code works just fine.<\/p>\n<p>The Implementation <script src=\"https:\/\/gist.github.com\/668230.js?file=ComplexBusinessOperations-1.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">public class ComplexBusinessOperations\n{\n    private int moneyEarnedSoFar;\n\n    public int MoneyEarnedSoFar\n    {\n        get { return moneyEarnedSoFar; }\n    }\n\n    public void EarnMoney(int investment)\n    {\n        EarnMoneySubTaks(investment);\n        EarnMoneySubTaks(investment);\n    }\n\n    private void EarnMoneySubTaks(int investment)\n    {\n        for (int i = 0; i &lt; investment; i++)\n        {\n            var result = EarnOneDollar();\n            moneyEarnedSoFar += result;\n        }\n    }\n\n    private int EarnOneDollar()\n    {\n        \/\/ This operation takes a while\n        Thread.Sleep(50);\n        return 1;\n    }\n}<\/code><\/pre><\/noscript><\/p>\n<p>The Test <script src=\"https:\/\/gist.github.com\/668230.js?file=ComplexBusinessOperationsTest-1.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">[Test]\npublic void EarnMoney()\n{\n    var toTest = new ComplexBusinessOperations();\n    toTest.EarnMoney(200);\n    Assert.AreEqual(400, toTest.MoneyEarnedSoFar);\n}<\/code><\/pre><\/noscript><\/p>\n<p>As said the method \u2018EarnOneDollar\u2019 takes a while. To improve the reactiveness of our desktop application we make this process asynchronous. First we make the \u2018EarnOneDollar\u2019-method asynchronous. In the \u2018EarnMoney-\u2018method we start the two sub task asynchronously and then wait until everything is done. In the test we wait for the result and then check if the property has the right value.<\/p>\n<p>The Implementation <script src=\"https:\/\/gist.github.com\/668230.js?file=ComplexBusinessOperations-2.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">public class ComplexBusinessOperations\n{\n    private int moneyEarnedSoFar;\n\n    public int MoneyEarnedSoFar\n    {\n        get { return moneyEarnedSoFar; }\n    }\n\n    public async Task EarnMoneyAsync(int investment)\n    {\n        var firstMoneyEarner = EarnMoneySubTaskAsync(investment);\n        var secondMoneyEarner = EarnMoneySubTaskAsync(investment);\n        await TaskEx.WhenAll(firstMoneyEarner, secondMoneyEarner);\n    }\n\n    private async Task EarnMoneySubTaskAsync(int investment)\n    {\n        for (int i = 0; i &lt; investment; i++)\n        {\n            var result = await EarnOneDollarAsync();\n            moneyEarnedSoFar += result;\n        }\n    }\n\n    private Task&lt;int&gt; EarnOneDollarAsync()\n    {\n        return TaskEx.Run(\n            () =&gt;\n                {\n                    \/\/ This operation takes a while\n                    Thread.Sleep(50);\n                    return 1;\n                });\n    }\n}<\/code><\/pre><\/noscript><\/p>\n<p>The Test <script src=\"https:\/\/gist.github.com\/668230.js?file=ComplexBusinessOperationsTest-2.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">[Test]\npublic void EarnMoney()\n{\n    var toTest = new ComplexBusinessOperations();\n    var task = toTest.EarnMoneyAsync(200);\n    task.Wait();\n    Assert.AreEqual(400, toTest.MoneyEarnedSoFar);\n}<\/code><\/pre><\/noscript><\/p>\n<p>After this refactoring we run the tests. To our surprise the test fails sometimes. And it fails with different values!<br \/>\n<a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/async-failure.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/async-failure.png\" alt=\"\" title=\"async-failure\" class=\"aligncenter size-full wp-image-1329\" width=\"600\" height=\"193\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/async-failure.png 600w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/async-failure-300x96.png 300w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/a><\/p>\n<h2>A Race Condition, Oh noes!<\/h2>\n<p>Obviously we\u2019ve introduced a race condition. However when that code runs in the regular desktop application it works fine. So why does it fail in the test setup? Remember my post about <a href=\"?p=1263\">the synchronization context?<\/a> This bites us here: Since there&#8217;s no synchronization context in the NUnit test-runner the continuations are executed on the thread-pool. This also means that the synchronization of our money counter variable is wrong. How do we fix that? Well we could synchronize the variable, but that\u2019s quite ugly and bloats the code. I suggest to setup the environment so that it mimics a desktop application. This means that there&#8217;s a message pump and a synchronization context.<\/p>\n<p>Let&#8217;s introduce a special \u2018test\u2019-message pump. It is based on the example implementation from my <a href=\"?p=1263\">previous post<\/a>.&nbsp; This message pump processes messages until some special condition is matched. We create a static utility method which sets up the  message pump and sets it as the synchronization context. This method expects a closure which contains the test to run. Additionally it passes an \u2018awaiter\u2019 to that test-closure. The \u2018awaiter\u2019 allows us to wait on a task and process messages meanwhile.<\/p>\n<p>The Test Utility <script src=\"https:\/\/gist.github.com\/668230.js?file=TestSyncContext.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">public static class TestSyncContext\n{\n    public static void Run(Action&lt;Awaiter&gt; testToRun)\n    {\n        using(var msgPump = new MyPrimitiveSynchronisationContext())\n        {\n            var syncContextBackup = SynchronizationContext.Current;\n            try\n            {\n                SynchronizationContext.SetSynchronizationContext(msgPump);\n                var awaiter = new Awaiter(msgPump);\n                msgPump.Post(obj =&gt; testToRun(awaiter), null);\n                msgPump.RunOneRound();\n            }\n            finally\n            {\n                SynchronizationContext.SetSynchronizationContext(syncContextBackup);\n            }\n        }\n    } \n\n}\n\npublic 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        while(!toWaitOn.IsCompleted)\n        {\n            syncContext.RunOneRound(); \n        }       \n    }\n}<\/code><\/pre><\/noscript><\/p>\n<p>The Message Pump \/ Synchronisation Context : Just the <a href=\"https:\/\/gist.github.com\/668230#file_my_primitive_synchronisation_context.cs\">link<\/a>, to keep this post smaller. It&#8217;s essentially the same as in my <a href=\"?p=1263\">previous post<\/a>.<\/p>\n<p>Now we\u2019re ready to update the test. We use this nice utility to provide a synchronization context for our test. We wrap our test in a closure and use the awaiter to wait for the process to finish <script src=\"https:\/\/gist.github.com\/668230.js?file=ComplexBusinessOperationsTest-3.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">[Test]\npublic void EarnMoney()\n{\n    TestSyncContext.Run(\n        awaiter=&gt;\n        {\n            var toTest = new ComplexBusinessOperations();\n            var task = toTest.EarnMoneyAsync(200);\n            awaiter.WaitFor(task);\n            Assert.AreEqual(400, toTest.MoneyEarnedSoFar);\n        });\n}<\/code><\/pre><\/noscript><\/p>\n<h2>Conclusion And Follow-Up<\/h2>\n<p>This time we\u2019ve looked at an example where the unit test fails due to invalid synchronization. It\u2019s really important to understand the concept of the synchronization context also in unit tests. To ensure correct synchronization we\u2019ve also introduced a utility class which sets up a special synchronization context for a test.<\/p>\n<p>There\u2019s more to come about async operations and unit testing. Meanwhile: Have a fun time playing with <a href=\"http:\/\/msdn.microsoft.com\/en-us\/vstudio\/async.aspx\">the Async CTP yourself<\/a>.<\/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 we explored some implications of the C# asynchronous operations 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\/1325"}],"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=1325"}],"version-history":[{"count":21,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1325\/revisions"}],"predecessor-version":[{"id":3880,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1325\/revisions\/3880"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=1325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=1325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=1325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}