How to generate automatic dummy data for .NET applications using Bogus
Tired of generating manual dummy/demo data? With Bogus, you can create realistic dummy data automatically without having to write thousands of lines of code with seed data.
β Christian Schou
I am sure you have been working on a project where you got a test environment and yet need some data to test all your functionality. Adding demo/dummy data can be time a consuming task for developers and if there is one thing I don't like, it's wasting my time with jobs like that.
Fortunately, Brian Chavez has created something called Bogus. Bogus is a simple fake data generator for .NET languages like C#, F#, and VB.NET. Bogus is actually just a C# port of faker.js
and has been inspired by FluentValidation
's syntax sugar.
By using Bogus we can help ourselves save a huge amount of time as developers. Bogus will do the heavy lifting for us and load the database, UI, and apps with fake data for us to test against.
If you are ready, let's get started generating automatic dummy data automatically for .NET using Bogus.
Final Result
By the end of this tutorial, your application is capable of creating responses like the one below:
[
{
"name": "Ergonomic Wooden Sausages",
"description": "The automobile layout consists of a front-engine design, with transaxle-type transmissions mounted at the rear of the engine and four wheel drive",
"adjective": "Small",
"material": "Wooden",
"price": "140,18",
"department": "Computers & Clothing",
"id": 24,
"created": "2022-10-09T11:39:15.71621+02:00"
},
{
"name": "Rustic Steel Tuna",
"description": "The automobile layout consists of a front-engine design, with transaxle-type transmissions mounted at the rear of the engine and four wheel drive",
"adjective": "Practical",
"material": "Plastic",
"price": "359,40",
"department": "Electronics",
"id": 25,
"created": "2022-10-09T11:39:15.716256+02:00"
},
{
"name": "Ergonomic Frozen Mouse",
"description": "Ergonomic executive chair upholstered in bonded black leather and PVC padded seat and back for all-day comfort and support",
"adjective": "Tasty",
"material": "Steel",
"price": "547,98",
"department": "Toys & Computers",
"id": 26,
"created": "2022-10-09T11:39:15.716261+02:00"
},
{
"name": "Incredible Fresh Sausages",
"description": "The slim & simple Maple Gaming Keyboard from Dev Byte comes with a sleek body and 7- Color RGB LED Back-lighting for smart functionality",
"adjective": "Licensed",
"material": "Granite",
"price": "132,01",
"department": "Baby, Kids & Clothing",
"id": 27,
"created": "2022-10-09T11:39:15.716266+02:00"
},
{
"name": "Generic Granite Salad",
"description": "The beautiful range of Apple NaturalΓ© that has an exciting mix of natural ingredients. With the Goodness of 100% Natural Ingredients",
"adjective": "Refined",
"material": "Steel",
"price": "174,47",
"department": "Shoes & Baby",
"id": 28,
"created": "2022-10-09T11:39:15.716272+02:00"
}
]
Requirements
To follow along in this tutorial or to implement Bogus in your own application, you will need the following:
- An IDE like Visual Studio or Rider.
- C# Knowledge (not advanced skills)
- A clean ASP.NET Core Web API (or an existing project)
Set up the project
I will be using a clean ASP.NET core Web API created by Visual Studio running on my macOS computer.
Create project structure
Create a new project and add the following folders to the root of your project named Entities
and Services
. The folder structure should look like the following now:
BogusDummyData/
ββ Connected Services/
ββ Dependencies/
β ββ Frameworks/
β ββ NuGet/
ββ Controllers
ββ Entities/
ββ Properties/
ββ Services/
Install Bogus in the project
Now that we have the project structure in place, let's add Bogus to our dependencies for the application.
Install-Package Bogus
Cleanup
By default, the API template from Microsoft includes a WeatherController and WeatherForeCast class. We don't need those for this project. Let's delete them.
That is the only housekeeping for this project.
Implement logic to use Bogus in .NET
Now for the fun part, where we actually get to make something that will help us create all the dummy data for testing, etc...
Create Entities
For this project, I have created two entities. A Base
entity and a Product
Entity. The Base
entity is useful as we can add default fields/properties in that and then inherit the Base
entity inside the Product
entity.
Add the two entities inside the Entities
folder we created earlier, and add the following code inside them:
Base Entity
using System;
namespace BogusDummyData.Entitites
{
public class Base
{
public int Id { get; set; }
public DateTime? Created { get; set; } = DateTime.Now;
}
}
Product Entity
namespace BogusDummyData.Entitites
{
public class Product : Base
{
public string? Name { get; set; }
public string? Description { get; set; }
public string? Adjective { get; set; }
public string? Material { get; set; }
public string? Price { get; set; }
public string? Department { get; set; }
}
}
If you take a look in the Commerce API for Bogus, you will quickly see that I have used the names on my fields from Bogus. You can read more about the Commerce API below:
Create Services for generating fake data
In order to generate some fake data for our controller or any other part of the program, we have to create a service that will generate these fake data for us. Create a new file named ProductService.cs
inside the Services
folder.
In this article, I will not split up the service interface and implementation into multiple files since the application is just for demo purposes and will only contain these data. Copy and paste the following data into ProductService.cs
:
using Bogus;
using BogusDummyData.Entitites;
namespace BogusDummyData.Services
{
public interface IProductService
{
Product GetSingleProduct();
List<Product> GetAllProducts(int amountOfProducts);
}
public class ProductService : IProductService
{
private static readonly Faker<Product> ProductFaker = new Faker<Product>()
.RuleFor(x => x.Id, x => x.IndexFaker + 1)
.RuleFor(x => x.Name, x => x.Commerce.ProductName())
.RuleFor(x => x.Description, x => x.Commerce.ProductDescription())
.RuleFor(x => x.Adjective, x => x.Commerce.ProductAdjective())
.RuleFor(x => x.Material, x => x.Commerce.ProductMaterial())
.RuleFor(x => x.Price, x => x.Commerce.Price())
.RuleFor(x => x.Department, x => x.Commerce.Department());
public List<Product> GetAllProducts(int amountOfProducts)
{
List<Product> products = ProductFaker.Generate(amountOfProducts);
return products;
}
public Product GetSingleProduct()
{
Product product = ProductFaker.Generate();
return product;
}
}
}
So what is happening above? Let's split this up into multiple parts:
First, we create the interface IProductService
containing the methods that we would like to be able to call from the controller.
public interface IProductService
{
Product GetSingleProduct();
List<Product> GetAllProducts(int amountOfProducts);
}
Then we got the ProductService
implementing the IProductService
interface. Here we got two methods GetSingleProduct();
and GetAllProducts(int x);
.
To generate fake data, we need a Faker
for the Product
class. Bogus allows us to do that by providing a Faker<T>
class we can consume to generate the fake object.
private static readonly Faker<Product> ProductFaker = new Faker<Product>()
.RuleFor(x => x.Id, x => x.IndexFaker + 1)
.RuleFor(x => x.Name, x => x.Commerce.ProductName())
.RuleFor(x => x.Description, x => x.Commerce.ProductDescription())
.RuleFor(x => x.Adjective, x => x.Commerce.ProductAdjective())
.RuleFor(x => x.Material, x => x.Commerce.ProductMaterial())
.RuleFor(x => x.Price, x => x.Commerce.Price())
.RuleFor(x => x.Department, x => x.Commerce.Department());
Some explanation of what happened in the Fake<Product>
class for our Product
.
- The first thing we do is initialize the
Faker<Product>
ProductFaker
object. - The configuration for each of the product properties in the
Product
class is configured by using theRuleFor()
method. As you probably already have guessed, the first parameter is the one from theProduct
class and the second parameter is the value we would like to set in theProduct property
from Bogus.
By specifying RuleFor(x => x.Id, x => x.IndexFaker + 1)
we will set the Id on the Product to increment by one each time a dummy product is generated when the service is running.
The rest of the properties are filled out using the Commerce API from Bogus.
To generate the dummy data we got two methods implemented from the interface for our product service.
GetAllProducts(int x)
public List<Product> GetAllProducts(int amountOfProducts)
{
List<Product> products = ProductFaker.Generate(amountOfProducts);
return products;
}
The Generate()
method takes in a parameter that allows us to generate more than one product. When you specify a value in the Generate()
method, you will get a List<T>
in return.
GetSingleProduct();
public Product GetSingleProduct()
{
Product product = ProductFaker.Generate();
return product;
}
To generate a single random product, we can call Generate()
without passing any value to the method.
Register Product Service in Program.cs
Because we rely on Dependency Injection in our controller for the product service, we have to register the product service in Program.cs
. All you have to do is add the product service as a transient. See line 11 below:
using BogusDummyData.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddTransient<IProductService, ProductService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Create the Product Controller
Bogus has now been configured for generating fake dummy data for our .NET application. Let's get the data presented in a nice way through Swagger.
Inside the Controllers
folder, add a new controller named ProductsController.cs
and add the following code inside it.
using BogusDummyData.Services;
using Microsoft.AspNetCore.Mvc;
namespace BogusDummyData.Controllers
{
[Route("api/[controller]")]
public class ProductsController : Controller
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet]
public IActionResult GetAll(int amount = 20)
{
return Ok(_productService.GetAllProducts(amount));
}
[HttpGet]
public IActionResult Get()
{
return Ok(_productService.GetSingleProduct());
}
}
}
In the products controller, we got two endpoints. The first endpoint GetAll(int amount = 20)
will return a list of products with random data. By default, if no value is submitted with the request, the service will generate 20 products in a list. The second endpoint Get()
will only return a single Product
containing random product (Commerce) data generated by Bogus.
Time for test
The Web API is now ready for some testing. Let's fire it up and make some requests for some product data.
GetAll()
returns the following when I request 3 products. Request: http://localhost:47916/api/Products/getall?amount=3
[
{
"name": "Tasty Steel Chips",
"description": "The automobile layout consists of a front-engine design, with transaxle-type transmissions mounted at the rear of the engine and four wheel drive",
"adjective": "Licensed",
"material": "Metal",
"price": "17,75",
"department": "Movies",
"id": 6,
"created": "2022-10-09T13:58:26.405205+02:00"
},
{
"name": "Unbranded Plastic Cheese",
"description": "New ABC 13 9370, 13.3, 5th Gen CoreA5-8250U, 8GB RAM, 256GB SSD, power UHD Graphics, OS 10 Home, OS Office A & J 2016",
"adjective": "Refined",
"material": "Steel",
"price": "93,83",
"department": "Jewelery",
"id": 7,
"created": "2022-10-09T13:58:26.405245+02:00"
},
{
"name": "Sleek Steel Car",
"description": "Ergonomic executive chair upholstered in bonded black leather and PVC padded seat and back for all-day comfort and support",
"adjective": "Licensed",
"material": "Fresh",
"price": "179,66",
"department": "Computers & Tools",
"id": 8,
"created": "2022-10-09T13:58:26.405248+02:00"
}
]
Get()
returns a single product as expected. Request: http://localhost:47916/api/Products/get
{
"name": "Fantastic Metal Pizza",
"description": "The slim & simple Maple Gaming Keyboard from Dev Byte comes with a sleek body and 7- Color RGB LED Back-lighting for smart functionality",
"adjective": "Rustic",
"material": "Wooden",
"price": "253,29",
"department": "Beauty",
"id": 9,
"created": "2022-10-09T14:00:21.830281+02:00"
}
It works! As you can see the id
is automatically incremented by every request we make for the API.
Summary
Bogus is a power full C# port of faker.js indeed! It allows us to generate a lot of demo data without it being lorem ipsum all the time, but with different texts that make more sense. The product data is not in relation to each other though, but it is better than lorem ipsum.
If you previously generated your dummy test data manually, those days are now over. With Bogus, you can generate thousands of products, users, etc... in seconds without having to do anything. Isn't that awesome!?
If you got any questions, please let me know in the comments. If you enjoyed this article and learned something need and would like to help me spread the word about TWC, please share it with your friends or colleagues. Until next time, happy coding! βοΈ π€