<?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>Arrange Act Assert &#187; NBuilder</title> <atom:link href="http://www.arrangeactassert.com/category/nbuilder/feed/" rel="self" type="application/rss+xml" /><link>http://www.arrangeactassert.com</link> <description>Jag Reehal on Agile Development, ASP.NET MVC and all manner of good stuff</description> <lastBuildDate>Thu, 24 Nov 2011 00:01:20 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /> <item><title>How NBuilder Could Help You Write Better .Net Unit Tests</title><link>http://www.arrangeactassert.com/how-nbuilder-could-help-you-write-better-net-unit-tests/</link> <comments>http://www.arrangeactassert.com/how-nbuilder-could-help-you-write-better-net-unit-tests/#comments</comments> <pubDate>Wed, 10 Mar 2010 22:00:51 +0000</pubDate> <dc:creator>Jag Reehal</dc:creator> <category><![CDATA[NBuilder]]></category> <category><![CDATA[Unit tests]]></category><guid
isPermaLink="false">http://www.arrangeactassert.com/?p=618</guid> <description><![CDATA[One of the biggest challenges when creating unit tests is to come up test data. It makes sense having someone other than you test your code, so how about having someone other than you generate the test input for your .Net unit tests. Data generation tools aren’t new concept and they come in many different [...]]]></description> <content:encoded><![CDATA[<p>One of the biggest challenges when creating unit tests is to come up test data.  It makes sense having someone other than you test your code, so how about having someone other than you generate the test input for your .Net unit tests.</p><p>Data generation tools aren’t new concept and they come in many different forms.  When I first saw <a
href="http://www.red-gate.com/products/sql_data_generator/index.htm">Red Gate Sql Data Generator</a> a couple of years ago, I thought to myself it&#8217;s a shame you need a database because this would have been great for unit and integration tests.</p><p>In this blog post I want to show you how <a
href="http://nbuilder.org">NBuilder</a> can be used when unit testing with .Net objects.  The NBuilder assembly can be downloaded here <a
href="http://code.google.com/p/nbuilder/">http://code.google.com/p/nbuilder/</a>.</p><p>In this blog post we will be using the product and category classes below</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
public class Product
{
    public Product()
    {
        Categories = new List&lt;Category&gt;();
    }

    public Guid Id { get; set; }
    public string Name { get; set; }
    public int Rating { get; set; }
    public decimal Price { get; set; }
    public bool InStock { get; set; }
    public List&lt;Category&gt; Categories { get; set; }

    public override string ToString()
    {
        return String.Format(&quot;Id:{0}, Name:{1}, Rating:{2}, Price:{3}, InStock:{4}, Categories:{5}&quot;, Id, Name, Rating, Price, InStock, Categories.Count);
    }
}

public class Category
{
    public string Name { get; set; }
}
</pre><h3 class="subheading">NBuilder default values</h3><p>The product class contains a variety of types.  When you run the following code to create 10 products</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
[Test]
public void Should_Create_Ten_Products()
{
    var products = Builder&lt;Product&gt;.CreateListOfSize(10).Build();
    products.Count().ShouldEqual(10);
}
</pre><p>this is the output</p><table
border=1><tr
align="center"  bgcolor="grey"><td>Id</td><td>Name</td><td>Rating</td><td>Price</td><td>InStock</td><td>Categories Count</td></tr><tr
align="center"><td>00000000-0000-0000-0000-000000000001</td><td>Name1</td><td>1</td><td>1</td><td>False</td><td>0</td></tr><tr
align="center"  bgcolor="#F1EDED"><td>00000000-0000-0000-0000-000000000002</td><td>Name2</td><td>2</td><td>2</td><td>True</td><td>0</td></tr><tr
align="center"><td>00000000-0000-0000-0000-000000000003</td><td>Name3</td><td>3</td><td>3</td><td>False</td><td>0</td></tr><tr
align="center"  bgcolor="#F1EDED"><td>00000000-0000-0000-0000-000000000004</td><td>Name4</td><td>4</td><td>4</td><td>True</td><td>0</td></tr><tr
align="center"><td>00000000-0000-0000-0000-000000000005</td><td>Name5</td><td>5</td><td>5</td><td>False</td><td>0</td></tr><tr
align="center"  bgcolor="#F1EDED"><td>00000000-0000-0000-0000-000000000006</td><td>Name6</td><td>6</td><td>6</td><td>True</td><td>0</td></tr><tr
align="center"><td>00000000-0000-0000-0000-000000000007</td><td>Name7</td><td>7</td><td>7</td><td>False</td><td>0</td></tr><tr
align="center"  bgcolor="#F1EDED"><td>00000000-0000-0000-0000-000000000008</td><td>Name8</td><td>8</td><td>8</td><td>True</td><td>0</td></tr><tr
align="center"><td>00000000-0000-0000-0000-000000000009</td><td>Name9</td><td>9</td><td>9</td><td>False</td><td>0</td></tr><tr
align="center"  bgcolor="#F1EDED"><td>00000000-0000-0000-0000-00000000000a</td><td>Name10</td><td>10</td><td>10</td><td>True</td><td>0</td></tr></table><p><br/></p><ul><li>For strings NBuilder suffixes the index number to the name of the property e.g. Name1</li><li>For numeric values such as int and decimal the default value is the index number</li><li>For guids a hexadecimal range is used</li><li>Boolean values alternate between true and false for each product</li><li>The categories collection is left empty.  This would have been null if we didn&#8217;t create a new collection in the constructor of the product class</li></ul><h3 class="subheading">Changing how NBuilder default values are created</h3><p>I really like how you can customize NBuilder and use your own convention for creating default values.</p><p>For example what if we wanted to change how guids are created.</p><p>One way to do this is to inherit from the RandomValuePropertyNamer class and override the GetGuid method as shown below.</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
public class JagsRandomValuePropertyNamer : RandomValuePropertyNamer
{
    protected override Guid GetGuid(System.Reflection.MemberInfo memberInfo)
    {
        return Guid.NewGuid();
    }
}
</pre><p>After setting the default property namer, all guids are created by calling Guid.NewGuid()</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
[Test]
public void Product_Should_Have_Guid_Assigned()
{
    BuilderSetup.SetDefaultPropertyNamer(new JagsRandomValuePropertyNamer());

    var product = Builder&lt;Product&gt;
        .CreateListOfSize(10)
        .WhereAll()
            .Have(p =&gt; p.Id = Guid.NewGuid())
        .Build();

    product[0].Id.ToString().ShouldNotEqual(&quot;00000000-0000-0000-0000-000000000001&quot;);
}
</pre><h3 class="subheading">Using the WhereAll method to set the InStock to always be true</h3><p>What if we wanted to change the InStock value to true for all the products in the collection.  This can be done using the WhereAll method as shown in the code below</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
[Test]
public void All_Products_Should_Be_In_Stock()
{
    var products = Builder&lt;Product&gt;
        .CreateListOfSize(10)
        .WhereAll()
            .Have(p =&gt; p.InStock = true)
        .Build();

    products.All(p =&gt; p.InStock).ShouldBeTrue();
}
</pre><h3 class="subheading">Using NBuilder to set parts of a collection</h3><p>There are two ways you can use Nbuilder to set values in parts of a collection.  The first is by using the first or last methods like so</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
[Test]
public void First_Two_Products_Should_Be_In_Stock()
{
    var products = Builder&lt;Product&gt;
        .CreateListOfSize(10)
        .WhereTheFirst(2)
            .Have(p =&gt; p.InStock = true)
        .Build();

    products[0].InStock.ShouldBeTrue();
    products[1].InStock.ShouldBeTrue();
}
</pre><p>the other is to use sections</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
[Test]
public void Mixture_Of_Products_In_Stock_Using_Sections()
{
    var products = Builder&lt;Product&gt;
        .CreateListOfSize(10)
        .WhereSection(0, 1)
            .Have(p =&gt; p.InStock = true)
        .WhereSection(2, 9)
            .Have(p =&gt; p.InStock = false)
        .Build();

    products[0].InStock.ShouldBeTrue();
    products[2].InStock.ShouldBeFalse();
}
</pre><h3 class="subheading">Using the UniqueRandomList to create unique random lists&#8230;</h3><p>So far we haven&#8217;t done anything with the category property.</p><p>What if you wanted to build a product collection with each product having a random number of categories?</p><p>By calling the HaveDoneToThem and the UniqueRandomList methods we can create a set of products with having different categories to one another</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
[Test]
public void Products_With_Random_Categories()
{
    var categories = Builder&lt;Category&gt;
        .CreateListOfSize(100)
        .Build();

    var products = Builder&lt;Product&gt;
        .CreateListOfSize(10)
        .WhereAll()
        .HaveDoneToThem(p =&gt; p.Categories.AddRange(Pick&lt;Category&gt;.UniqueRandomList(2).From(categories)))
        .Build();

    var productCategoryOne = products[0].Categories[0].Name;
    var productCategoryTwo = products[1].Categories[0].Name;

    productCategoryOne.ShouldNotBeTheSameAs(productCategoryTwo);
}
</pre><h3 class="subheading">Extending NBuilder with a Lorem Ipsum string generator</h3><p>One thing I really like about NBuilder is the ability to extend it.</p><p>The code below shows how easy it is to have product names randomly using Lorem Ipsum just by creating a extension method like this</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
public static class StringExtensions
{
    public const string LoremIpsum = &quot;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.&quot;;

    public static IOperable&lt;Product&gt; HavingRandomLoremIpsumProductName(this IOperable&lt;Product&gt; operable)
    {
        ((IDeclaration&lt;Product&gt;)operable).ObjectBuilder.With(x =&gt; x.Name = LoremIpsum.Substring(0, new Random().Next(446)));
        return operable;
    }
}
</pre><p>this can be used to generate products with random names like this</p><pre class="brush: csharp; gutter: false; title: ; toolbar: true; notranslate">
[Test]
public void Products_With_Random_LoremIpsum_Names()
{
    var products = Builder&lt;Product&gt;
        .CreateListOfSize(10)
        .WhereAll()
            .HavingRandomLoremIpsumProductName()
        .Build();

    var nameOfProductOne = products[0].Name;
    var nameOfProductTwo = products[1].Name;

    nameOfProductOne.ShouldNotBeTheSameAs(nameOfProductTwo);
}
</pre><h3 class="subheading">Jag Reehal’s Final Thought on &#8216;How NBuilder Could Help You Write Better .Net Unit Tests’</h3><p>I think frameworks like NBehave could really have a big impact on how you go about having to create test data.  The fluent interface is fantastic and it&#8217;s so easy to customize.</p><p>NBuilder contains a lot more features than I have covered in this post so if you like what you&#8217;ve seen make sure you check out the <a
href="http://nbuilder.org/Documentation">NBuilder documentation</a>.</p><p>For the future I’m hoping <a
href="http://fluentnhibernate.org/">Fluent NHibernate</a> and NBuilder could work together.  For example when you define class maps in Fluent NHibernate you can specify the length of string column.  If NBuilder could use information like this when generating data that would really be something special.</p> ]]></content:encoded> <wfw:commentRss>http://www.arrangeactassert.com/how-nbuilder-could-help-you-write-better-net-unit-tests/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> </channel> </rss>
<!-- Served from: www.arrangeactassert.com @ 2012-02-05 23:28:12 by W3 Total Cache -->
