Getting Started with Dossier

This page will help you get started with Dossier. You'll be up and running in a jiffy!

Add NuGet package

The best way to get started with Dossier is to install the package into your test project via NuGet:

Install-Package TestStack.Dossier

Building an object, creating a custom test data builder or generating a value?

Are you:

Create a custom test data builder class

If you want to build a custom builder class, e.g. for a domain object, you can use the builder as documentation and also to make the experience of building that class in your tests more rich.

Consider the following example of a domain object:

public class Customer
{
    protected Customer() {}

    public Customer(string firstName, string lastName, int yearJoined)
    {
        if (string.IsNullOrEmpty(firstName))
            throw new ArgumentNullException("firstName");
        if (string.IsNullOrEmpty(lastName))
            throw new ArgumentNullException("lastName");

        FirstName = firstName;
        LastName = lastName;
        YearJoined = yearJoined;
    }

    public virtual int CustomerForHowManyYears(DateTime since)
    {
        if (since.Year < YearJoined)
            throw new ArgumentException("Date must be on year or after year that customer joined.", "since");
        return since.Year - YearJoined;
    }

    public virtual string FirstName { get; private set; }
    public virtual string LastName { get; private set; }
    public virtual int YearJoined { get; private set; }
}

If you decide to create a CustomerBuilder custom test data builder class for it then you start by extending Dossier's TestDataBuilder class. The first generic parameter is the class that you are writing a builder for (the Customer class in this case) and the second generic parameter is the builder class itself (CustomerBuilder in this case).

It might be surprising to have this recursive type definition, but it is needed to facilitate fluent method chaining for the base class methods (e.g. Set).

public class CustomerBuilder : TestDataBuilder<Customer, CustomerBuilder>
{
  public CustomerBuilder()
  {
    // Can set up defaults here - any that you don't set or subsequently override
    //   will have an anonymous value generated by default
    WhoJoinedIn(2013);
  }

  // Note: the methods are virtual - this is important if you want to build lists (as per below)
  public virtual CustomerBuilder WithFirstName(string firstName)
  {
    return Set(x => x.FirstName, firstName);
  }

  // Note: we typically only start with the methods that are strictly needed so the
  //   builders are quick to write and aren't bloated
  public virtual CustomerBuilder WithLastName(string lastName)
  {
    return Set(x => x.LastName, lastName);
  }

  public virtual CustomerBuilder WhoJoinedIn(int yearJoined)
  {
    return Set(x => x.YearJoined, yearJoined);
  }

  // This method is optional, by default it uses `BuildUsing<PublicPropertySettersFactory>()`
  protected override Customer BuildObject()
  {
    return BuildUsing<CallConstructorFactory>();
    // or, if you need more control / can't use the auto-construction assumptions
    return new Customer(
      Get(x => x.FirstName),
      Get(x => x.LastName),
      Get(x => x.YearJoined)
    );
  }
}

Note: that overriding the BuildObject method is optional.

Use the builder in a test

var customer = new CustomerBuilder()
	.WithFirstName("Robert")
  .Build();

Where next?

Consider using the Object Mother pattern in combination with the builders. See Rob Moore's blog post for a description of the theory behind this approach.

The usage documentation should get you across the other capabilities of this library. It's probably best to start with Basic builder methods.