DEV Community

Robin van der Knaap
Robin van der Knaap

Posted on • Originally published at Medium on

AutoPoco, create meaningful test data based on your domain objects. (.NET)

Creating test data for your applications is usually a cumbersome and not too inspiring exercise, to say the least. Lately I discovered a nice tool called AutoPoco which is created by Rob Ashton. AutoPoco enables you to generate meaningful test data based on your domain objects (poco’s). AutoPoco is able to generate data for individual unit tests, or you can use AutoPoco to generate large amounts of test data to populate your database.

In this article I’ll give a short introduction to AutoPoco and explain how to customize AutoPoco to enable the generation of test data which is meaningful to your project and not just some randomly generated values.

I also created a sample app hosted on github, which contains some basic usage stuff and some custom datasources I wrote. A live version of the sample app is located here

Notice: Source code in this article is based on the latest version of AutoPoco residing in the trunk. The trunk contains some breaking changes with the official v1.0 release and because of that the source code used in this article will not work with the v1 release. The trunk is located here. You can also use the autopoco.dll which is included in the sample app, if you don’t feel like compiling the dll yourself. I will update this article and the sample app when Rob decides to release the next version of AutoPoco.

How does it work?

Basically AutoPoco examines your domain objects using reflection and assigns datasources to each property/field of your domain object. The assignment can be done automagically (convention over configuration), or you can assign datasources yourself. When generating test data each datasource creates meaningful test data to populate the assigned property. Here’s a quick example:

First, create a domain object for which test data will be generated:

public class User
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
public DateTime DateOfBirth { get; set; }
}
view raw gistfile1.txt hosted with ❤ by GitHub

Setup an AutoPoco factory and assign datasources to the properties of the domain object:

// Create factory for poco's and setup datasources
var pocoFactory = AutoPocoContainer.Configure(x =>
{
x.Conventions(c => c.UseDefaultConventions());
x.AddFromAssemblyContainingType<User>();
x.Include<User>()
.Setup(u => u.Email).Use<EmailAddressSource>()
.Setup(u => u.Firstname).Use<FirstNameSource>()
.Setup(u => u.Lastname).Use<LastNameSource>()
.Setup(u => u.DateOfBirth).Use<DateOfBirthSource>();
});
view raw gistfile1.txt hosted with ❤ by GitHub

Create an AutoPoco session:

var pocoSession = pocoFactory.CreateSession();

Tell AutoPoco to generate 10 users:

var users = pocoSession.List(10).Get();

And here’s the result:

AutoPoco is also able to set fixed values for certain properties and allows for invocation of methods on the domain objects. More information on installing and configuring AutoPoco can be found at http://autopoco.codeplex.com/documentation

Roll your own datasources

AutoPoco has some built-in datasources, like Email, Firstname, Lastname etc. In a real world scenario the built-in datasources won’t get you far. Luckily it’s easy to create your own datasources for AutoPoco.

The easiest way to create a custom datasource is to create a class that inherits from the DatasourceBase class:

public class ExampleSource : DatasourceBase<string>
{
public override string Next(IGenerationContext context)
{
throw new NotImplementedException();
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

As you can see, there’s only one method you have to implement, the Next method. The DatasourceBase class uses generics to determine the returntype, in this case a string, but this can just as easy be any other object. As an example I will create a datasource which provides company names:

public class CompanySource : DatasourceBase<String>
{
private readonly Random _random = new Random(1337);
public override string Next(IGenerationContext context)
{
return Companies[_random.Next(0, Companies.Length)];
}
private static readonly string[] Companies = new[]{
"Acme, inc.",
"Widget Corp",
"123 Warehousing",
"Demo Company",
"Smith and Co.",
"Foo Bars",
"ABC Telecom",
"Fake Brothers",
"QWERTY Logistics",
"Demo, inc.",
"Sample Company",
"Sample, inc",
"Acme Corp",
"Allied Biscuit",
"Ankh-Sto Associates",
"Extensive Enterprise",
"Galaxy Corp",
"Globo-Chem",
"Mr. Sparkle",
"Moes Tavern",
"Central Perk",
"Chasers"
};
}
view raw gistfile1.txt hosted with ❤ by GitHub

Once created this datasource can be used in the same way as the built-in datasources. Extending our previous example, the configuration of AutoPoco would look like this using the company datasource:

var pocoFactory = AutoPocoContainer.Configure(x =>
{
x.Conventions(c => c.UseDefaultConventions());
x.AddFromAssemblyContainingType&ltUser>();
x.Include<User>()
.Setup(u => u.Email).Use<EmailAddressSource>()
.Setup(u => u.Firstname).Use<FirstNameSource>()
.Setup(u => u.Lastname).Use<LastNameSource>()
.Setup(u => u.DateOfBirth).Use<DateOfBirthSource>()
.Setup(u => u.Company).Use<CompanySource>();
});
view raw gistfile1.txt hosted with ❤ by GitHub

Which results in:

Concluding

It’s very easy to generate test data with AutoPoco, and what I like most, you can give meaning to your test data by creating your own datasources.

I created a little project on github to host some of the custom datasources I wrote. The project includes an asp.net mvc example using some of the built-in and all of the custom datasources I use to generate data. The output of the example project can be found here. Feel free to use the datasources anyway you like. Included datasources are:

  • EnumSource
  • BooleanSource
  • CitySource
  • CompanySource
  • DateTimeSource
  • DecimalSource
  • DoubleSource
  • DutchCitySource
  • DutchMiddlenameSource
  • DutchMobileSource
  • DutchPostalSource
  • DutchTelephoneSource
  • ExtendedEmailAddressSource
  • FloatSource
  • IntegerSource
  • PostalSource
  • StreetSource
  • TimeSpanSource
  • UrlSource

Copyright © 2010 Webpirates. All source code used in this article is licensed under the Lesser General Public License.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more