TDD http://rickgaribay.net/category/30.aspx TDD en-US Rick G. Garibay rickgaribay@hotmail.com Subtext Version 1.9.5.176 TDD Katas http://rickgaribay.net/archive/2009/09/30/tdd-katas.aspx <p>I don’t do a new and notable list, but if I did, Roy’s TDD Katas would be on my list: <a title="http://5whys.com/blog/how-to-measure-programmer-productivity-using-tdd-katas.html" href="http://5whys.com/blog/how-to-measure-programmer-productivity-using-tdd-katas.html">http://5whys.com/blog/how-to-measure-programmer-productivity-using-tdd-katas.html</a></p> <p>Just brilliant.</p><img src="http://rickgaribay.net/aggbug/263.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2009/09/30/tdd-katas.aspx Thu, 01 Oct 2009 00:50:26 GMT http://rickgaribay.net/archive/2009/09/30/tdd-katas.aspx#feedback http://rickgaribay.net/comments/commentRss/263.aspx http://rickgaribay.net/services/trackbacks/263.aspx A Pragmatic Team TDD Covenant http://rickgaribay.net/archive/2009/09/22/a-pragmatic-team-tdd-covenant.aspx <h1><font size="4">“As a team, we commit to test-first development, preferring unit tests over integration tests, and reluctantly accepting integration tests over no tests at all. As such, we write just enough integration tests to provide end to end smoke testing and no more.”</font></h1> <p> </p> <p>In distinguishing between unit tests and integration tests, we honor the following foundational practices to which we largely credit <a target="_blank" href="http://www.agiledata.org/essays/tdd.html">Kent Beck</a>, <a target="_blank" href="http://xunitpatterns.com/Unit%20Test%20Rulz.html">Michael Feathers</a>, and <a target="_blank" href="http://www.butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd">Bob Martin</a>.</p> <ol> <li>You are not allowed to write any production code unless it is to make a failing unit test pass.</li> <li>You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.</li> <li>You are not allowed to write any more production code than is sufficient to pass the one failing unit test.</li> <li>A test is not a unit test (but is instead an integration test) if:</li> </ol> <ul> <ul> <li>it talks to the database </li> <li>it communicates across the network</li> <li>it touches the file system</li> <li>it can’t run at the same time as any of your other unit tests</li> <li>you have to do special things to your environment (such as editing config files) to run it.</li> </ul> </ul> <p>       5. Above all else, be pragmatic and use your judgment. </p><img src="http://rickgaribay.net/aggbug/261.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2009/09/22/a-pragmatic-team-tdd-covenant.aspx Tue, 22 Sep 2009 19:24:27 GMT http://rickgaribay.net/archive/2009/09/22/a-pragmatic-team-tdd-covenant.aspx#feedback 3 http://rickgaribay.net/comments/commentRss/261.aspx http://rickgaribay.net/services/trackbacks/261.aspx Take Me with You! Ensuring Team Build Brings Dependencies Along for the Ride http://rickgaribay.net/archive/2009/08/27/take-me-with-you-ensuring-team-build-brings-dependencies-along.aspx <p>As part of an automated build at a client, we currently have over 150 unit tests that run as part of each automated build. Some of the tests are also integration tests which serve to automatically smoke test the freshly compiled application code.</p> <p>One of our apps makes use of an XML file that allows the ability to dynamically change behavior of a component without requiring an app domain recycle. A static method uses a FileWatcher to detect a change and applies the configuration changes at runtime accordingly. But I digress…</p> <p>When Team Build executes your unit tests, it creates a special directory on the build agent called TestResults.The TestResults folder includes a .trx file that captures the build results in XML along with a folder for each build/run which isolates all required test assemblies and other dependant assemblies for execution. The App.config file will automatically be copied over and renamed to AssemblyName.dll.config. This is fine and dandy, but what about other dependencies like the XML file?</p> <p>The answer is different depending on whether you are running your tests locally from Visual Studio or if Team Build is running your tests as part of an automated build, but you must be familiar with both techniques to accomplish a consistent and repeatable means for taking the XML file along for the ride under both scenarios which you will undoubtedly need to understand because chances are you are (or at least should be) running all unit tests locally before checking into source control, right? Right?</p> <p><strong>Local Dependencies</strong></p> <p>When running and debugging unit tests using Visual Studio and a just-in-time test runners like TestDriven.NET that have an external dependency such as an XML file, you must ensure the dependency is in the binary root relative to the executing assembly. This is also true when using other unit testing frameworks like NUnit, which I talk about <a href="http://rickgaribay.net/archive/2007/03/21/Making-Configuration-Files-Available-to-NUnit.aspx">here</a>.</p> <p>Right click the resource in the test project, click properties and set “Copy to Output Directory” to “Copy Always”:</p> <p><a href="http://rickgaribay.net/Images/CustomContent/TakeMewithYouEnsuringMSBuildBringsDepend_E003/image.png"><img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="240" height="94" src="http://rickgaribay.net/Images/CustomContent/TakeMewithYouEnsuringMSBuildBringsDepend_E003/image_thumb.png" /></a> </p> <p>This will ensure that the dependency is copied to the bin directory just as other dependencies like DLLs and App.Config/Web.Config are automatically.</p> <p>At this point, the XML file can be referenced in the root of the bin which is relative to the executing assembly.</p> <p><strong></strong></p> <p><strong>Team Build Dependencies</strong></p> <p>As I mentioned earlier, when Team Build executes unit tests, it moves all required assemblies and assembly dependencies to a TestResults folder. While this includes App.config and Web.config files, other dependencies are not copied regardless of whether you specify “Copy to Output Directory” to “Copy Always” as shown above. This makes sense, because when Team Build runs, the unit test project is no longer located with the rest of the source- instead it is copied to the TestResults folder and prepped for execution.</p> <p>There are two ways to address this.</p> <p>The first option is to mark each test method with a <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.deploymentitemattribute(VS.80).aspx">DeploymentItem</a> attribute. This is documented <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.deploymentitemattribute(VS.80).aspx">here</a>, so I won’t go into much into it. The basic usage is to mark you test method with the DeploymentItem attribute, providing a parameter with the path and filename of the dependency:</p> <!-- code formatted by http://manoli.net/csharpformat/ --><style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <div class="csharpcode"> <pre class="alt"><span class="lnum"> 1: </span>[TestMethod]</pre> <pre><span class="lnum"> 2: </span> [DeploymentItem(<span class="str">"../../MyExternalDependency.xml"</span>)]</pre> <pre class="alt"><span class="lnum"> 3: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> FooShouldReturnBar()</pre> <pre><span class="lnum"> 4: </span> { </pre> <pre class="alt"><span class="lnum"> 5: </span> </pre> <pre><span class="lnum"> 6: </span> <span class="rem">//...</span></pre> <pre class="alt"><span class="lnum"> 7: </span> </pre> <pre><span class="lnum"> 8: </span> }</pre> </div> <p>When the assembly that includes the test class loads, the attribute is reflected and the dependent file is copied to the TestResults folder. You can also add the attribute at the test class level and it will have the same effect.</p> <p>The draw back of this approach is that it requires that you apply this attribute to the test class and it is really quite noisy because it is only used when running tests with Team Build or the Test List Editor.</p> <p>To keep things cleaner, I prefer to make these dependencies configuration driven. So, similarly to setting the “Copy to Output Directory” to “Copy Always” for just-in-time testing, you can determine dependencies that should be copied to the TestResults folder using a global configuration setting that will apply to all tests: Test Run Configuration.</p> <p>Go to Test, “Edit Test Run Configuration” and click on the configuration file as shown below:</p> <p> </p> <p><a href="http://rickgaribay.net/Images/CustomContent/TakeMewithYouEnsuringMSBuildBringsDepend_E003/image_3.png"><img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="240" height="113" src="http://rickgaribay.net/Images/CustomContent/TakeMewithYouEnsuringMSBuildBringsDepend_E003/image_thumb_3.png" /></a> </p> <p>Now, click on the Deployment option on the left, ensure “Enable Deployment” is checked, and either click “Add File” to add a specific file, or “Add Directory” to include the entire contents of a directory:</p> <p> </p> <p><a href="http://rickgaribay.net/Images/CustomContent/TakeMewithYouEnsuringMSBuildBringsDepend_E003/image_4.png"><img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="240" height="170" src="http://rickgaribay.net/Images/CustomContent/TakeMewithYouEnsuringMSBuildBringsDepend_E003/image_thumb_4.png" /></a> </p> <p> </p> <p>The localtestrun.testrunconfig file will be configured with the dependencies specified and this file will be consulted just prior to kicking off a test run to ensure that all dependencies are copied to the TestResults folder.</p> <p>That’s really all there is to it. Thanks to <a target="_blank" href="http://blogs.neudesic.com/blogs/brendon_birdoes/default.aspx">Brendon Birdoes</a> for turning <a target="_blank" href="http://www.rickgaribay.net/contact.aspx">me</a> on to the DeploymentItem attribute which I was not familiar with.</p><img src="http://rickgaribay.net/aggbug/258.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2009/08/27/take-me-with-you-ensuring-team-build-brings-dependencies-along.aspx Fri, 28 Aug 2009 03:05:14 GMT http://rickgaribay.net/archive/2009/08/27/take-me-with-you-ensuring-team-build-brings-dependencies-along.aspx#feedback http://rickgaribay.net/comments/commentRss/258.aspx http://rickgaribay.net/services/trackbacks/258.aspx Unit Testing Microsoft Sync Framework 2.0 &amp; WCF http://rickgaribay.net/archive/2009/08/17/unit-testing-microsoft-sync-framework-amp-wcf.aspx <p>I just wrapped up some work for a client that entails exposing the Sync Framework 2.0 via WCF.</p> <p>We are using Sync Framework 2.0 CTP 2 to support occasionally connected client scenarios between applications deployed out in the edge and core services hosted in the client’s cloud. I am using WCF to wrap the Sync Fx APIs to support interoperable synchronization support via SOAP 1.1. This way, any client can on-ramp with the core services and essentially become self-provisioned by initiating and initial synchronization to download required data necessary to come on line. In addition, when events happen out on the edge, the client can synchronize each event back to the cloud using an upload semantic. </p> <p>There are many benefits to using the Sync Fx as opposed to rolling your own, and one benefit is the extremely simple provider model which makes basic synchronization scenarios a breeze, particularly between relational replicas such as SQL Server. Note however, that Sync Fx is fully extensible and capable of synchronizing any two memory streams. </p> <p>So, the basic idea is that given a SyncProvider for the local and remote replica, any two data sources/applications can be synchronized:</p> <p><a href="http://rickgaribay.net/Images/CustomContent/UnitTestingMicrosoftSyncFrameworkWCF_13226/image_5.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/Images/CustomContent/UnitTestingMicrosoftSyncFrameworkWCF_13226/image_thumb_5.png" width="640" height="394" /></a> </p> <p>In my scenario, the local client out in the edge utilizes the out of the box SqlSyncProvider. The goal was to expose the cloud over HTTP using SOAP, which required some understanding of the underlying APIs. From there, it was simply a matter of wrapping the Sync Fx APIs in a service layer, so that I would arrive at something like this:</p> <p><a href="http://rickgaribay.net/Images/CustomContent/UnitTestingMicrosoftSyncFrameworkWCF_13226/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/Images/CustomContent/UnitTestingMicrosoftSyncFrameworkWCF_13226/image_thumb_6.png" width="640" height="371" /></a> </p> <p>By providing a proxy to the orchestrator, I was able to implement a proxy which is polymorphic with RelationalSyncProvider. </p> <p>Immediately it should be obvious that this is not your typical integration scenario. Essentially, I am extending a framework by exposing it over WCF so that any orchestrator can leverage the WebSyncProvider. </p> <p>I started the implementation by writing some tests. It was simple enough to extract an interface for the RelationalSyncProvider type because it is abstract. I used RhinoMocks to stub it, which worked great but where I ran into problems was in recording expectations on the return types because there are not a lot of test seams in the framework. With the absence of setters on main properties that I needed to assert, I needed a way to reach into the framework types and manipulate them so that I could develop the CUT  (in this case the ServiceContract implementation) independent of the framework.<a href="http://rickgaribay.net/Images/CustomContent/UnitTestingMicrosoftSyncFrameworkWCF_13226/clip_image002.jpg"><img style="border-right-width: 0px; margin: 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="clip_image002" border="0" alt="clip_image002" align="right" src="http://rickgaribay.net/Images/CustomContent/UnitTestingMicrosoftSyncFrameworkWCF_13226/clip_image002_thumb.jpg" width="240" height="227" /></a></p> <p><a href="http://msdn.microsoft.com/en-us/library/bb514191.aspx" target="_blank">Publicize.exe</a> works pretty nicely for what I was looking for. </p> <p>For example, let’s say I want to stub a closed/framework type so that I can actually write my test without having to resort to integrating with the framework (which wouldn’t be a unit test at all), in this case, a couple of types in the Microsoft.Syncronization.dll assembly. </p> <p>I run Publicize.exe Microsoft.Syncronization.dll and it generates a shadow assembly called Microsoft.Syncronization_Accessor.dll, which takes all types, adds _Accessor and exposes all non-public members as public as shown in Reflector on the right. </p> <p>This pretty powerful. </p> <p>I can now stub the return type of any closed/framework class and test as long as I am asserting *properties*, which is pretty common:</p> <!-- code formatted by http://manoli.net/csharpformat/ --><style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <div class="csharpcode"> <pre class="alt"><span class="lnum"> 1: </span> </pre> <pre><span class="lnum"> 2: </span> [TestMethod]</pre> <pre class="alt"><span class="lnum"> 3: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> GetChangesShouldReturnNumberOfChangesApplied()</pre> <pre><span class="lnum"> 4: </span> {</pre> <pre class="alt"><span class="lnum"> 5: </span> MockRepository mockRepository = <span class="kwrd">new</span> MockRepository();</pre> <pre><span class="lnum"> 6: </span> </pre> <pre class="alt"><span class="lnum"> 7: </span> RelationalSyncProvider provider = mockRepository.Stub&lt;RelationalSyncProvider&gt;();</pre> <pre><span class="lnum"> 8: </span> </pre> <pre class="alt"><span class="lnum"> 9: </span> </pre> <pre><span class="lnum"> 10: </span> <span class="kwrd">using</span> (mockRepository.Record())</pre> <pre class="alt"><span class="lnum"> 11: </span> {</pre> <pre><span class="lnum"> 12: </span> </pre> <pre class="alt"><span class="lnum"> 13: </span> <span class="rem">// Set up the out parameter on RelationalSyncProvider Stub</span></pre> <pre><span class="lnum"> 14: </span> DbSyncContext changeDataRetriever = <span class="kwrd">new</span> DbSyncContext();</pre> <pre class="alt"><span class="lnum"> 15: </span> </pre> <pre><span class="lnum"> 16: </span> <span class="rem">// Set up ScopeProgress property on DbySyncContext instance</span></pre> <pre class="alt"><span class="lnum"> 17: </span> <span class="rem">/*</span></pre> <pre><span class="lnum"> 18: </span><span class="rem"> * Note that in order to test for number of changes applied, we need to reach into the</span></pre> <pre class="alt"><span class="lnum"> 19: </span><span class="rem"> * DbSyncScopeProgress and access the _totalChanges private member </span></pre> <pre><span class="lnum"> 20: </span><span class="rem"> * so that public properties can be asserted. This is because the TotalChanges property only has a </span></pre> <pre class="alt"><span class="lnum"> 21: </span><span class="rem"> * getter, so the only way to influence the value is through it's backing field.</span></pre> <pre><span class="lnum"> 22: </span><span class="rem"> */</span> </pre> <pre class="alt"><span class="lnum"> 23: </span> </pre> <pre><span class="lnum"> 24: </span> DbSyncScopeProgress dbSyncScopeProgress = <span class="kwrd">new</span> DbSyncScopeProgress();</pre> <pre class="alt"><span class="lnum"> 25: </span> </pre> <pre><span class="lnum"> 26: </span> <span class="rem">// Reference the actual object which will be accessed by the generated accessor</span></pre> <pre class="alt"><span class="lnum"> 27: </span> PrivateObject obj = <span class="kwrd">new</span> PrivateObject(dbSyncScopeProgress);</pre> <pre><span class="lnum"> 28: </span> </pre> <pre class="alt"><span class="lnum"> 29: </span> <span class="rem">// Generated accessor which wraps the type to be exposed using reflection.</span></pre> <pre><span class="lnum"> 30: </span> <span class="rem">// Instead of writing the reflection code manually, Publicize.exe was run against the real assembly,</span></pre> <pre class="alt"><span class="lnum"> 31: </span> <span class="rem">// which in turn generated reflection wrappers for *all* types.</span></pre> <pre><span class="lnum"> 32: </span> </pre> <pre class="alt"><span class="lnum"> 33: </span> DbSyncScopeProgress_Accessor dbSyncScopeProgressAccessor = <span class="kwrd">new</span> DbSyncScopeProgress_Accessor(obj);</pre> <pre><span class="lnum"> 34: </span> </pre> <pre class="alt"><span class="lnum"> 35: </span> <span class="rem">// Look ma, I am accessing a private field</span></pre> <pre><span class="lnum"> 36: </span> dbSyncScopeProgressAccessor._tablesProgress = <span class="kwrd">new</span> List&lt;DbSyncTableProgress&gt;();</pre> <pre class="alt"><span class="lnum"> 37: </span> </pre> <pre><span class="lnum"> 38: </span> </pre> <pre class="alt"><span class="lnum"> 39: </span> <span class="rem">// Now we need to repeat the same process again for this type, which is at the heart of what we need to</span></pre> <pre><span class="lnum"> 40: </span> <span class="rem">// gain access to.</span></pre> <pre class="alt"><span class="lnum"> 41: </span> DbSyncTableProgress dbSyncTableProgress = <span class="kwrd">new</span> DbSyncTableProgress();</pre> <pre><span class="lnum"> 42: </span> </pre> <pre class="alt"><span class="lnum"> 43: </span> <span class="rem">// Provides the accessor with a reference to the actual object</span></pre> <pre><span class="lnum"> 44: </span> obj = <span class="kwrd">new</span> PrivateObject(dbSyncTableProgress);</pre> <pre class="alt"><span class="lnum"> 45: </span> </pre> <pre><span class="lnum"> 46: </span> <span class="rem">// Generated accessor which wraps the type to be exposed using reflection.</span></pre> <pre class="alt"><span class="lnum"> 47: </span> <span class="rem">// Instead of writing the reflection code manually, Publicize.exe was run against the real assembly,</span></pre> <pre><span class="lnum"> 48: </span> <span class="rem">// which in turn generated reflection wrappers for *all* types.</span></pre> <pre class="alt"><span class="lnum"> 49: </span> DbSyncTableProgress_Accessor dbSyncTableProgressAccessor = <span class="kwrd">new</span> DbSyncTableProgress_Accessor(obj);</pre> <pre><span class="lnum"> 50: </span> </pre> <pre class="alt"><span class="lnum"> 51: </span> <span class="rem">// Set the _rowsApplied field so that the stubbed return instance of DbSyncScopeProgress can be asserted.</span></pre> <pre><span class="lnum"> 52: </span> dbSyncTableProgressAccessor._rowsApplied = 42;</pre> <pre class="alt"><span class="lnum"> 53: </span> </pre> <pre><span class="lnum"> 54: </span> <span class="rem">// Add the dbSyncTableProgress to the private collection</span></pre> <pre class="alt"><span class="lnum"> 55: </span> dbSyncScopeProgressAccessor._tablesProgress.Add(dbSyncTableProgress);</pre> <pre><span class="lnum"> 56: </span> </pre> <pre class="alt"><span class="lnum"> 57: </span> </pre> <pre><span class="lnum"> 58: </span> <span class="rem">// Now, set the property to our used and abused instance of DbSyncScopeProgress</span></pre> <pre class="alt"><span class="lnum"> 59: </span> changeDataRetriever.ScopeProgress = dbSyncScopeProgress;</pre> <pre><span class="lnum"> 60: </span> </pre> <pre class="alt"><span class="lnum"> 61: </span> <span class="rem">// Provider is implemented in COM so out params are prevelant (yuk)</span></pre> <pre><span class="lnum"> 62: </span> <span class="kwrd">object</span> changeDataRetrieverObj = changeDataRetriever;</pre> <pre class="alt"><span class="lnum"> 63: </span> </pre> <pre><span class="lnum"> 64: </span> <span class="rem">// Set the expectation</span></pre> <pre class="alt"><span class="lnum"> 65: </span> provider.GetChangeBatch(0, <span class="kwrd">null</span>, <span class="kwrd">out</span> changeDataRetrieverObj);</pre> <pre><span class="lnum"> 66: </span> </pre> <pre class="alt"><span class="lnum"> 67: </span> <span class="rem">// Initialize params</span></pre> <pre><span class="lnum"> 68: </span> SyncIdFormatGroup idFormats = <span class="kwrd">new</span> SyncIdFormatGroup();</pre> <pre class="alt"><span class="lnum"> 69: </span> SyncKnowledge destinationKnowledge = <span class="kwrd">new</span> SyncKnowledge();</pre> <pre><span class="lnum"> 70: </span> ForgottenKnowledge sourceForgottenKnowledge = <span class="kwrd">new</span> ForgottenKnowledge();</pre> <pre class="alt"><span class="lnum"> 71: </span> </pre> <pre><span class="lnum"> 72: </span> <span class="rem">// Stub the return, including the object reference to DbSyncContext</span></pre> <pre class="alt"><span class="lnum"> 73: </span> LastCall.Return(<span class="kwrd">new</span> ChangeBatch(idFormats, destinationKnowledge, sourceForgottenKnowledge))</pre> <pre><span class="lnum"> 74: </span> .OutRef(changeDataRetrieverObj).IgnoreArguments();</pre> <pre class="alt"><span class="lnum"> 75: </span> }</pre> <pre><span class="lnum"> 76: </span> </pre> <pre class="alt"><span class="lnum"> 77: </span> IRelationalSyncManager manager = <span class="kwrd">new</span> RelationalSyncManager();</pre> <pre><span class="lnum"> 78: </span> </pre> <pre class="alt"><span class="lnum"> 79: </span> <span class="rem">// Inject the stub</span></pre> <pre><span class="lnum"> 80: </span> manager.Provider = provider;</pre> <pre class="alt"><span class="lnum"> 81: </span> </pre> <pre><span class="lnum"> 82: </span> SyncKnowledge localKnowledge = <span class="kwrd">new</span> SyncKnowledge();</pre> <pre class="alt"><span class="lnum"> 83: </span> DbSyncContext returnedContext = <span class="kwrd">new</span> DbSyncContext();</pre> <pre><span class="lnum"> 84: </span> returnedContext.ScopeProgress = <span class="kwrd">new</span> DbSyncScopeProgress();</pre> <pre class="alt"><span class="lnum"> 85: </span> </pre> <pre><span class="lnum"> 86: </span> </pre> <pre class="alt"><span class="lnum"> 87: </span> var changeBatch = manager.GetChanges(0, localKnowledge, <span class="kwrd">out</span> returnedContext);</pre> <pre><span class="lnum"> 88: </span> </pre> <pre class="alt"><span class="lnum"> 89: </span> DbSyncContext context = returnedContext;</pre> <pre><span class="lnum"> 90: </span> </pre> <pre class="alt"><span class="lnum"> 91: </span> Assert.IsTrue(context.ScopeProgress.TotalChangesApplied ==42);</pre> <pre><span class="lnum"> 92: </span> </pre> <pre class="alt"><span class="lnum"> 93: </span> }</pre> </div> <p> </p> <p>There is a bit of work here, but with a bit of elbow grease thanks to Visual Studio Test Tools, RhinoMocks, reflection and a little code generation the framework is testable.</p><img src="http://rickgaribay.net/aggbug/256.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2009/08/17/unit-testing-microsoft-sync-framework-amp-wcf.aspx Tue, 18 Aug 2009 04:46:33 GMT http://rickgaribay.net/archive/2009/08/17/unit-testing-microsoft-sync-framework-amp-wcf.aspx#feedback 2 http://rickgaribay.net/comments/commentRss/256.aspx http://rickgaribay.net/services/trackbacks/256.aspx Book Review: The Art of Unit Testing by Roy Osherove http://rickgaribay.net/archive/2009/07/19/book-review-the-art-of-unit-testing-by-roy-o.aspx <p>In short, if you want a tactical book on unit testing that distills the passion and love of an expert practitioner into a very readable yet reference-friendly text on unit testing, this is it. <br /> <br /> If you are new to unit testing or TDD, this book will demystify the practices, tools and techniques that would otherwise take years and lots of frustration to get right. <br /> <br /> If you are an experienced practitioner of unit testing and TDD, and are already practicing SOLID, TOOD, and BDD not just as a flavor of the week but as a way of life, this book will provide unambiguous insight into different approaches that will help you refine your existing techniques or at a minimum, validate your approach which is always valuable to any developer who has an opportunity to review his/her techniques with a seasoned master. This book will afford you that opportunity. <br /> <br /> While the book cites excellent references for TDD and design patterns, if there is one thing that I thought was missing was a narrative- even if by way of an appendix- that ties all of the techniques covered together in an example of building the example Logger component using TDD. I understand that this book is not about TDD per se, but at the same time, that's like a book on scuba equipment that teaches you precisely how to pressurize your CO2 tank, keep your mask from fogging up and care and maintenance of your scuba suit not being about scuba diving. <br /> <br /> That said, knowing Roy, it must have been painful to resist a detailed examination on TDD, but, for this book to be effective, it had to be relatively short, to the point and most of all pragmatic for it to succeed at filling the void on the topic of unit testing techniques and practices. To that end, Roy hits the mark very elegantly without being pretentious, catering to those who test first, test last or don't (yet) test at all. While I would love for everyone to pick this book up and start doing TDD today, even if you aren't yet convinced on TDD, applying these techniques to writing code that is testable, and learning how to test the right things will be an instant asset to your product, your team and your organization.</p> <p>You can find the book on Amazon.com: <font face="Arial"><a href="http://www.amazon.com/gp/product/1933988274">http://www.amazon.com/gp/product/1933988274</a></font></p><img src="http://rickgaribay.net/aggbug/249.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2009/07/19/book-review-the-art-of-unit-testing-by-roy-o.aspx Sun, 19 Jul 2009 20:54:53 GMT http://rickgaribay.net/archive/2009/07/19/book-review-the-art-of-unit-testing-by-roy-o.aspx#feedback http://rickgaribay.net/comments/commentRss/249.aspx http://rickgaribay.net/services/trackbacks/249.aspx Rhino Mocks Ignore Arguments http://rickgaribay.net/archive/2009/06/12/rhino-mocks-ignore-arguments.aspx <p>I am writing some tests for a project I am working on called Green Fee Broker.</p> <p>The first thing I am doing is mocking the business layer for the WCF service that I am writing so I can inject it into the service’s constructor and write the service while isolating dependencies:</p> <blockquote> <p>MockRepository mockRepository = new MockRepository(); </p> </blockquote><blockquote> <p>IBookingManager manager = mockRepository.DynamicMock&lt;IBookingManager&gt;();</p> </blockquote> <p>Next, I set an expectation that CreateTeeTime is called on the manager mock, which is injected into the service constructor:</p> <blockquote> <p>Expect.Call(manager.CreateTeeTime(course, DateTime.Now)).Return(teeTimeStub);</p> </blockquote> <p>Finally, I ReplayAll to record the mock, call the service and assert that I am getting back a TeeTime object:</p> <blockquote> <p>mockRepository.ReplayAll(); </p> <p>BookingService service = new BookingService(manager);</p> </blockquote><blockquote> <p>TeeTime teeTime = service.CreateTeeTime(course, DateTime.Now); </p> <p>Assert.IsTrue(teeTime.ConfirmationNumber == "ABC123"); </p> </blockquote> <p>Unfortunately, there is a bug in the line of code that sets up the expectation. With Rhino Mocks, for an expected behavior to be a match, the parameters must be an exact match. Notice the second parameter uses DateTime.Now. This means that the expectation will have a different parameter than the actual call, even if it is just a few milleseconds of a difference. As a result, the assertion will fail because the return is null.</p> <p>The solution is to add the IgnoreArguments method call on the expectation:</p> <blockquote> <p>Expect.Call(manager.CreateTeeTime(course, DateTime.Now)).Return(teeTimeStub).IgnoreArguments(); </p> </blockquote> <p>The IgnoreArguments() call will ensure that the parameters are discarded completely in determining a match.</p> <p>Now I am green, and good to go!</p> <p><a href="http://rickgaribay.net/Images/CustomContent/RhinoMocksIgnoreArguments_A8F/image.png"><img title="image" style="BORDER-TOP-WIDTH: 0px; DISPLAY: inline; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="163" alt="image" width="644" border="0" src="http://rickgaribay.net/Images/CustomContent/RhinoMocksIgnoreArguments_A8F/image_thumb.png" /></a></p><img src="http://rickgaribay.net/aggbug/247.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2009/06/12/rhino-mocks-ignore-arguments.aspx Fri, 12 Jun 2009 07:47:26 GMT http://rickgaribay.net/archive/2009/06/12/rhino-mocks-ignore-arguments.aspx#feedback http://rickgaribay.net/comments/commentRss/247.aspx http://rickgaribay.net/services/trackbacks/247.aspx