AAA Pattern in C#

The Arrange Act Assert pattern (aka AAA), is just a simple way to structure your unit tests. It’s simple, but it help produces clearer test.

[TestMethod]
public void GetDocuments_when_called_with_empty_Guid_returns_an_empty_List()
{
    // Arrange
    var documentStore = new DocumentStore();

    // Act
    var result = documentStore.GetDocuments(Guid.Empty); 

    // Assert
    Assert.AreEqual(0, result.Count());
}

When writing unit tests with this pattern, you should put all of your initialization at the start of your test, your action under test next and then your assert(s). I separate all of those sections with comments to make to intent come out. Of course this is a simple test. Other tests would have many lines in the arrange section and possibly more than one in the assert section.

This separation makes it easier when someone (or you) reads your test. You can quickly get your eye to what is actually being tested. The actual method under test. A good rule to go by, is that the Act section should only contain one method call.

Otherwise it’s either initialization/preparation code that needs to go in the arrange section, or you are testing more than one thing. In this case, refactor your test to make it two tests.

You can also quickly get to the Assert section. While this seems simple, believe me, it very helpful when you need to quickly understand a failing test.

As for the Asserts, I have seen some sources say you should only have one assert per test. I find this is a little extreme. While having too many asserts is a sign you are testing many concepts at once and should split a test, I see nothing wrong with having two, three or four asserts in a test. The most important thing is to test a single concept in a single test rather than have only one assert.

To speed up writing my unit tests and to remember using the AAA pattern, I made a snippet in Visual Studio:

[TestMethod]
public void MethodName_WhenCondition_ExpectedValue()
{
    // Arrange
            

    // Act


    // Assert

}

I called the snippet testa, to differentiate it with the existing test snippet.

I also modified the default Visual Studio test file template. This is the template that is called when you create a new test source file. Since the method defines an empty test, I modified it to use the same code as in the previous snippet.

Test Method Name

As you may have noticed, my snippet has a template for the test method name. Following this template not only helps me think about what the test should do, it also makes for tests names that read like documentation. When I open the method list drop down in Visual Studio, I can just read the method names to know how the class behaves.

Test Methods in Visual Studio

Having a test method with a name like TestGetDocumentsEmptyList will just make everyone scratch their heads and loose precious time reading and deciphering what the test is actually doing. With a good naming scheme, you can read the method names and skip reading the actual test methods.

One last thing. While I always name my methods using camelCase, I make an exception for test methods. Since I write them out like sentences and I consult the method names afterward, I personally find them easier to read when they are written with underscores.

Update

Someone requested the code for the snippet after the initial posting, so here it is:

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>
        Test AAA
      </Title>     

      <Description>
        Test with the AAA (Arrange Act Assert) pattern. 
      </Description>

      <Shortcut>
        testa
      </Shortcut>
    </Header>

    <Snippet>
      <Code Language="CSharp">
        <![CDATA[[TestMethod]
        public void MethodName_condition_expectedValue()
        {
            // Arrange 


            // Act 


            // Assert           

        }]]>
      </Code>
    </Snippet>
  </CodeSnippet>

  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>
        TestInitialize
      </Title>

      <Description>
        TestInitialize template.
      </Description>

      <Shortcut>
        ti
      </Shortcut>
    </Header> 

    <Snippet>    
      <Code Language="CSharp">
        <![CDATA[[TestInitialize]
        public void TestInitialize()
        {           

        }]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

TestDataBuilder in C# 4

Creating data for unit tests can get cumbersome. There exists some patterns to speed up the process, like Object Mother and Test Data Builder.

I particularly like the Test Data Builder pattern, which I am currently using in my day to day work.

Existing pattern

Here is a pretty standard version of it:

public class BlogPostDataBuilder
{
    private DateTime publishDate;
    private Blogger blogger;

    public BlogPostDataBuilder()
    {
        blogger = new BloggerDataBuilder().Build(); 
        publishDate = DateTime.Now;
    }
                
    public BlogPost Build()
    {
        var blogPost = new BlogPost(blogger, publishDate);
        blogPost.AddTag("test tag");

        return blogPost;
    }

    public BlogPostDataBuilder WithPublishDate(DateTime publishDate)
    {
        this.publishDate = publishDate;
        return this;
    }

    public BlogPostDataBuilder WithBlogger(Blogger blogger)
    {
         this.blogger = blogger;
         return this;
    }
}

In the constructor, you initialize the data members to a standard value that can be used for most tests. Then, you can use your Test Data Builder in the following fashion:

var testBlogPost = new BlogPostDataBuilder().Build();

This simplifies the act of supplying your test objects with dummy data when you do not care about the value of said data. When you do care about the data, for example you have a test that needs to verify that X happens when the publishDate is in the future, you can only specify the values which are important for the test at hand.

var futureDate = DateTime.Now.AddDays(1);

var testBlogPost = new BlogPostDataBuilder()
                       .WithPublishDate(futureDate)
                       .Build();

This pattern makes it very clear which information is important in your test by making it very salient, while abstracting the non essential information.

Notice that the With methods return a Test Data Builder, so you can chain as many With method as you like.

A word of advice, when you write a new Test Data Builder, there is no need to write With methods for those properties that you don’t need to override right now. This will lessen the initial time investment of writing the Test Data Builder. Beside, as they say, YAGNI (you ain’t gonna need it). It is always safer the wait until you need something right now before starting to write it.

If you need to write a new test in the future which needs a specific property, like setting a specific post category, you create a new With method. Since none of your old tests are using this new With method, they will not be affected.

public BlogPost Build()
{
    var blogPost = new BlogPost(blogger, publishDate);
    blogPost.AddTag("test tag");

    if (category != null)
        blogPost.AddCategory(category);

    return blogPost;
}

public BlogPostDataBuilder WithCategory(Category category)
// ...

Using Test Data Builder will not only speed up writing subsequent tests. It will make the tests clearer. Finally it will also reduce the impact of a change in how you create your objects, which will lessen the pain of refactoring your tests.

Enter C# 4

So this was a pretty standard implementation of the pattern. Some of the new features of C# 4, namely named arguments and default parameters, got me thinking of a new way to implement this.

Here it is:

public class BlogPostDataBuilder
{
    private Blogger blogger;
    private Category category;

    public BlogPostDataBuilder(Blogger blogger = null, Category category = null)
    {
        this.blogger = blogger;
        this.category = category;
    }
                
    public BlogPost Build()
    {
        if (blogger == null)
            blogger = new BloggerDataBuilder().Build();

        var blogPost = new BlogPost(blogger, DateTime.Now);
           
        if (category != null)
            blogPost.AddCategory(category);

        return blogPost;
    }
}

And you would use it likewise:

var testBlogger = new Blogger();
var testCategory = new Category();

var testBlogPost = new BlogPostDataBuilder(blogger: testBlogger,
                                           category: testCategory)
                       .Build();

On the plus side, there is no need to code the With methods, and the resulting class is much leaner. Using the builder is also less verbose.

On the negative side, you run into a problem with DateTime parameters since you cannot use a DateTime as a constant for the default value of a default parameter. There are two ways to get around this.

The first is to provide a WithPublishDate method. This mix the two approach but it works. The other would be to make PublishDate a Nullable DateTime in your builder class.

Conclusion

If you have any opinions regarding the traditional Test Data Builder versus the C# 4 one, please leave a comment!