{"metadata":{"image":[],"title":"","description":""},"api":{"url":"","auth":"required","params":[],"results":{"codes":[]},"settings":""},"next":{"description":"","pages":[]},"title":"Getting Started with Dossier","type":"basic","slug":"getting-started","excerpt":"This page will help you get started with Dossier. You'll be up and running in a jiffy!","body":"[block:api-header]\n{\n \"type\": \"basic\",\n \"title\": \"Add NuGet package\"\n}\n[/block]\nThe best way to get started with Dossier is to install the package into your test project via NuGet:\n\n> Install-Package TestStack.Dossier\n[block:api-header]\n{\n \"type\": \"basic\",\n \"title\": \"Building an object, creating a custom test data builder or generating a value?\"\n}\n[/block]\nAre you:\n\n* [Building a DTO, view model, or other class you don't want to write a custom test data builder class for](doc:create-object-without-requiring-custom-builder-cla)?\n* [Generating a value](doc:anonymous-values-and-equivalence-classes)?\n* Creating a custom test data builder class? Carry on reading...\n[block:api-header]\n{\n \"type\": \"basic\",\n \"title\": \"Create a custom test data builder class\"\n}\n[/block]\nIf 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.\n\nConsider the following example of a domain object:\n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"public class Customer\\n{\\n protected Customer() {}\\n\\n public Customer(string firstName, string lastName, int yearJoined)\\n {\\n if (string.IsNullOrEmpty(firstName))\\n throw new ArgumentNullException(\\\"firstName\\\");\\n if (string.IsNullOrEmpty(lastName))\\n throw new ArgumentNullException(\\\"lastName\\\");\\n\\n FirstName = firstName;\\n LastName = lastName;\\n YearJoined = yearJoined;\\n }\\n\\n public virtual int CustomerForHowManyYears(DateTime since)\\n {\\n if (since.Year < YearJoined)\\n throw new ArgumentException(\\\"Date must be on year or after year that customer joined.\\\", \\\"since\\\");\\n return since.Year - YearJoined;\\n }\\n\\n public virtual string FirstName { get; private set; }\\n public virtual string LastName { get; private set; }\\n public virtual int YearJoined { get; private set; }\\n}\",\n \"language\": \"csharp\"\n }\n ]\n}\n[/block]\nIf 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).\n\nIt 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](doc:basic-builder-methods)).\n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"public class CustomerBuilder : TestDataBuilder<Customer, CustomerBuilder>\\n{\\n public CustomerBuilder()\\n {\\n // Can set up defaults here - any that you don't set or subsequently override\\n // will have an anonymous value generated by default\\n WhoJoinedIn(2013);\\n }\\n\\n // Note: the methods are virtual - this is important if you want to build lists (as per below)\\n public virtual CustomerBuilder WithFirstName(string firstName)\\n {\\n return Set(x => x.FirstName, firstName);\\n }\\n\\n // Note: we typically only start with the methods that are strictly needed so the\\n // builders are quick to write and aren't bloated\\n public virtual CustomerBuilder WithLastName(string lastName)\\n {\\n return Set(x => x.LastName, lastName);\\n }\\n\\n public virtual CustomerBuilder WhoJoinedIn(int yearJoined)\\n {\\n return Set(x => x.YearJoined, yearJoined);\\n }\\n\\n // This method is optional, by default it uses `BuildUsing<PublicPropertySettersFactory>()`\\n protected override Customer BuildObject()\\n {\\n return BuildUsing<CallConstructorFactory>();\\n // or, if you need more control / can't use the auto-construction assumptions\\n return new Customer(\\n Get(x => x.FirstName),\\n Get(x => x.LastName),\\n Get(x => x.YearJoined)\\n );\\n }\\n}\",\n \"language\": \"csharp\"\n }\n ]\n}\n[/block]\nNote: that overriding the BuildObject method is [optional](doc:build-objects-without-calling-constructor).\n[block:api-header]\n{\n \"type\": \"basic\",\n \"title\": \"Use the builder in a test\"\n}\n[/block]\n\n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"var customer = new CustomerBuilder()\\n\\t.WithFirstName(\\\"Robert\\\")\\n .Build();\",\n \"language\": \"csharp\"\n }\n ]\n}\n[/block]\n\n[block:api-header]\n{\n \"type\": \"basic\",\n \"title\": \"Where next?\"\n}\n[/block]\nConsider using the [Object Mother pattern](http://martinfowler.com/bliki/ObjectMother.html) in combination with the builders. See [Rob Moore's blog post](https://robdmoore.id.au/blog/2013/05/25/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder) for a description of the theory behind this approach.\n\nThe usage documentation should get you across the other capabilities of this library. It's probably best to start with [Basic builder methods](doc:basic-builder-methods).","updates":["5ccc1edce5206200440465ac"],"order":1,"isReference":false,"hidden":false,"sync_unique":"","link_url":"","link_external":false,"_id":"553dec6a1a946a0d00ad6f2d","user":"54c4b05742190d0d00f5fbde","category":{"sync":{"isSync":false,"url":""},"pages":["553dec6a1a946a0d00ad6f2d","5543575b62b30e0d004b16f9","5561ed6c4bfe45170030a059"],"title":"Getting Started","slug":"getting-started","order":0,"from_sync":false,"reference":false,"_id":"553dec691a946a0d00ad6f2b","__v":3,"version":"553dec691a946a0d00ad6f2a","createdAt":"2015-04-27T07:59:37.956Z","project":"553dec691a946a0d00ad6f27"},"createdAt":"2015-04-27T07:59:38.667Z","version":{"version":"1.0","version_clean":"1.0.0","codename":"","is_stable":true,"is_beta":false,"is_hidden":false,"is_deprecated":false,"categories":["553dec691a946a0d00ad6f2b","5543585f795b590d001dc89a"],"_id":"553dec691a946a0d00ad6f2a","createdAt":"2015-04-27T07:59:37.477Z","project":"553dec691a946a0d00ad6f27","__v":2,"releaseDate":"2015-04-27T07:59:37.477Z"},"__v":10,"githubsync":"","project":"553dec691a946a0d00ad6f27"}
Getting Started with Dossier
This page will help you get started with Dossier. You'll be up and running in a jiffy!