<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>notepuddle &#187; TDD</title>
	<atom:link href="http://notepuddle.com/category/tdd/feed/" rel="self" type="application/rss+xml" />
	<link>http://notepuddle.com</link>
	<description>a blog</description>
	<lastBuildDate>Wed, 08 Sep 2010 23:16:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>TDD and Commerce Server 2007: Custom Rollback</title>
		<link>http://notepuddle.com/2009/01/28/tdd-and-commerce-server-2007-custom-rollback/</link>
		<comments>http://notepuddle.com/2009/01/28/tdd-and-commerce-server-2007-custom-rollback/#comments</comments>
		<pubDate>Thu, 29 Jan 2009 01:58:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CommerceServer]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://notepuddle.com/?p=102</guid>
		<description><![CDATA[In my previous post I mentioned using a TransactionScope to rollback Commerce Server database updates, when unit testing, may not always work. Turns out it doesn&#8217;t work with the profile subsystem. To verify this, I coded an example similar to the address example on MSDN, resulting in the following test: [Fact] public void Should_save_address_changes() { [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous <a href="http://notepuddle.com/2009/01/22/tdd-and-commerce-server-2007-getting-started/">post</a> I mentioned using a <code>TransactionScope</code> to rollback Commerce Server database updates, when unit testing, may not always work. Turns out it doesn&#8217;t work with the profile subsystem.</p>
<p>To verify this, I coded an example similar to the address example on <a href="http://msdn.microsoft.com/en-us/library/ms865038.aspx">MSDN</a>, resulting in the following test:</p>
<pre class="prettyprint"><code>[Fact]
public void Should_save_address_changes() {
    var addressId = Guid.NewGuid();
    var addressService = new AddressService(TestProfileContext);
    var address = createNewAddress(addressService, addressId);

    addressService.Save(address);

    var savedAddress = addressService.Find(addressId);
    Assert.Equal(address.Line1, savedAddress.Line1);
    Assert.Equal(address.City, savedAddress.City);
    Assert.Equal(address.State, savedAddress.State);
    Assert.Equal(address.ZipCode, savedAddress.ZipCode);
}</code></pre>
<p>For this test, I extended the <code>CommerceFixture</code> class (created in my previous post) to create a <code>TestProfileContext</code> instance. If this test is executed, it will always save a new address to the Commerce Server Profiles Database. If we try adding an <code>AutoRollback</code> attribute to the test, the new address doesn&#8217;t get rolled back.</p>
<p>To fix this we can call <code>TestProfileContext.DeleteProfile</code> when the test completes. An easy way to do this, while making the code exception safe, is to create a scope class that implements <code>IDisposable</code>. This allows us to wrap the test in a <code>using</code> block, reducing the amount of code we need to type. Here&#8217;s an example implementation:</p>
<pre class="prettyprint"><code>public class ProfileScope : IDisposable {
    private readonly ProfileContext _profileContext;
    private readonly string _keyValue;
    private readonly string _profileType;

    public ProfileScope(ProfileContext context, string keyValue, string profileType) {
        _profileContext = context;
        _keyValue = keyValue;
        _profileType = profileType;
    }

    public void Dispose() {
        _profileContext.DeleteProfile(_keyValue, _profileType);
    }
}</code></pre>
<p>Now we can update the test, adding a using block with our scope object:</p>
<pre class="prettyprint"><code>[Fact]
public void Should_save_address_changes() {
    //arrange

    using (new ProfileScope(TestProfileContext, addressId.ToString(),
        AddressService.ProfileName)) {

        addressService.Save(address);

        //assert
    }
}</code></pre>
<p>We can trim the code down even further by adding a helper method to the base test class, <code>CommerceFixture</code>:</p>
<pre class="prettyprint"><code>public class CommerceFixture {
    ...
    public static ProfileScope ProfileScope(string keyValue, string profileType){
        return new ProfileScope(TestProfileContext, keyValue, profileType);
    }
    ...
}</code></pre>
<p>Which gives us our final version:</p>
<pre class="prettyprint"><code>[Fact]
public void Should_save_address_changes() {
    //arrange

    using (ProfileScope(addressId.ToString(), AddressService.ProfileName)) {
        addressService.Save(address);

        //assert
    }
}</code></pre>
<p>You can download the code for this example <a href='http://notepuddle.com/wp-content/uploads/2009/01/cs2007_customrollback.zip'>here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://notepuddle.com/2009/01/28/tdd-and-commerce-server-2007-custom-rollback/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TDD and Commerce Server 2007: Getting Started</title>
		<link>http://notepuddle.com/2009/01/22/tdd-and-commerce-server-2007-getting-started/</link>
		<comments>http://notepuddle.com/2009/01/22/tdd-and-commerce-server-2007-getting-started/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 04:12:08 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CommerceServer]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://notepuddle.com/?p=47</guid>
		<description><![CDATA[Mixing Commerce Server 2007 with unit testing frameworks is a little tricky. The few examples I&#8217;ve seen use MsTest specific features to route tests through ASP.NET or IIS when executing, providing the following drawbacks: Increased test execution time (sucks worse when running on a VPC) Increased cost for creating tests Techniques like dependency injection can [...]]]></description>
			<content:encoded><![CDATA[<p>Mixing Commerce Server 2007 with unit testing frameworks is a little tricky. The few examples I&#8217;ve seen use MsTest specific features to route tests through ASP.NET or IIS when executing, providing the following drawbacks:</p>
<ol>
<li>Increased test execution time (sucks worse when running on a VPC)</li>
<li>Increased cost for creating tests</li>
</ol>
<p>Techniques like dependency injection can be used to significantly reduce the number of tests that require a web host for execution. I&#8217;m using the Orders subsystem here, but the same techniques can be used with other subsystems as well.</p>
<h3>Example Code</h3>
<p>For this example I <a href="http://msdn.microsoft.com/en-us/library/aa544681.aspx">unpacked the CSharp.pup</a> file to create a new site named <em>CommerceSample</em>. You can download the example code <a href="http://notepuddle.com/wp-content/uploads/2009/01/starting_tdd_cs2007.zip">here</a>.</p>
<h3>Breaking Dependencies</h3>
<p>Commerce Server is tightly coupled to ASP.NET and this causes problems when trying to execute Commerce Server API code outside of a web application. Suppose we try to execute the following code within a unit testing framework:</p>
<pre class="prettyprint"><code>var userId = Guid.NewGuid();
var basket = OrderContext.Current.GetBasket(userId);
</code></pre>
<p>This produces a <code>NullReferenceException</code> due to an uninitialized singleton, <code>OrderContext.Current</code>. In a web application scenario this context is initialized by the <code>HttpModule <a href="http://msdn.microsoft.com/en-us/library/microsoft.commerceserver.runtime.orders.commerceordermodule.commerceordermodule.aspx">CommerceOrderModule</a></code>.</p>
<h3>Establishing a Test Context</h3>
<p>To execute code like this within a testing framework, we need to create an instance of <code>OrderContext</code>. One approach is to create a custom base class for tests requiring the use of an <code>OrderContext</code>, as shown below:</p>
<pre class="prettyprint"><code>public class CommerceFixture {
    public const string SiteName = "CommerceSample";

    public static readonly OrderContext TestOrderContext =
        OrderContext.Create(SiteName);
}</code></pre>
<p>If I have a test that requires an <code>OrderContext</code>, my test class can now extend this class and have access to the <code>TestOrderContext</code> instance. <strong>One thing to point out</strong>: <code>OrderContext.Create</code> will also initialize <code>OrderContext.Current</code>, so technically you don&#8217;t need to store the reference in an accessible property.</p>
<h3>Wrapping and Injecting Context Objects</h3>
<p>When working with context objects, I like to create wrappper types and inject the context into the wrapper. This allows for the following benefits:</p>
<ol>
<li>The ability to add new behavior to context objects (the usual benefit of wrapper classes)</li>
<li>No dependence on singletons (a lot of material has been written about this already)</li>
<li>Narrowing the API. Sometimes context objects can be a dumping ground for anything and everything. Wrapper classes provide a nice way to offer a subset of this functionality specific to my application.</li>
</ol>
<h3>Rolling Back Updates</h3>
<p>If a test updates a database, we want to make sure the updates are removed upon test completion, preventing unwanted side effects. Most mature testing frameworks provide some form of a rollback attribute, which wraps each test in a <code>TransactionScope</code> instance (if you&#8217;re stuck with MsTest, you can wrap your test code in a <code>using TransactionScope</code> block).</p>
<p><strong>Note</strong>: Originally I was told using a <code>TransactionScope</code> might not work with Commerce Server API&#8217;s due to legacy COM code, so I&#8217;ve actually never used this during full project development. I didn&#8217;t realize this worked until playing with this example while creating this post. One context type it might not work with is the <code>ProfileContext</code>. That said, there&#8217;s more than one way to rollback changes. I&#8217;ll discuss the rollback approach I&#8217;ve used before in a subsequent post.</p>
<h3>An Example</h3>
<p>Lets polish the <a href="http://msdn.microsoft.com/en-us/library/aa545295.aspx">recurring order</a> example from MSDN. I&#8217;d like to have a method that accepts a user id and a template name (basket name) and returns a basket that is already populated with items from the saved template:</p>
<pre class="prettyprint"><code>var cartService = new ShoppingCartService(orderContext);
var cart = cartService.CreateFromRecurringOrder(userId, templateName);</code></pre>
<p><code>ShoppingCartService</code> is an example of a thin wrapper, where the context is injected in.</p>
<p>To setup a test I need to create a recurring order template in the database, so my service class can find it. This is the update I want rolled back upon test completion. My final test looks like this:</p>
<pre class="prettyprint"><code>[Fact, AutoRollback]
public void Should_create_new_order_from_recurring_order_for_user() {
    var userId = Guid.NewGuid();
    var templateName = "MonthlyOrder";
    var cartService = new ShoppingCartService(TestOrderContext);

    var recurringOrder = buildRecurringOrder(cartService, userId, templateName);
    var cart = cartService.CreateFromRecurringOrder(userId, templateName);

    Assert.Equal(recurringOrder.LineItems.Count, cart.LineItems.Count);
}</code></pre>
<p>Where <code>buildRecurringOrder</code> is a helper function that creates an order template in the database. For this test I used <a href="http://www.codeplex.com/xunit">xUnit.net</a>. When the test completes, the order I saved will no longer exist. You can use the <a href="http://msdn.microsoft.com/en-us/library/ms915815.aspx">Customer and Orders Manager</a> to verify that your tests are not leaking baskets and orders.</p>
<h3>Future Topics</h3>
<p>In subsequent posts I&#8217;ll discuss the following topics:</p>
<ol>
<li>Using custom scope objects for situations where TransactionScope might not work</li>
<li>How to handle pipeline execution with testing frameworks</li>
<li>Testing with Commerce Server 2009</li>
</ol>
<h3>Related Information</h3>
<ol>
<li><a href="http://martinfowler.com/articles/injection.html">Dependency Injection</a></li>
<li>Misko Hevery discussing <a href="http://misko.hevery.com/2009/01/04/interfacing-with-hard-to-test-third-party-code/">hard to test third party code</a></li>
<li>Context object pain. See Misko <a href="http://misko.hevery.com/2008/07/24/how-to-write-3v1l-untestable-code/">here</a></li>
<li>Singleton pain. See Misko <a href="http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/">again</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://notepuddle.com/2009/01/22/tdd-and-commerce-server-2007-getting-started/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.630 seconds -->

