C# library to populate object with random data [closed]
We don’开发者_运维百科t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Improve this questionOriginal close reason(s) were not resolved
I want to populate my object with random data (for testing purposes), is there a library to do it?
Some kind of reflection method that will traverse object graph and initialize primitive properties like (string, int, DateTime, etc) (but do it the deep way, including collections, child objects, etc)
Bogus
Bogus is a simple and sane fake data generator for C# and .NET. A C# port of faker.js and inspired by FluentValidation's syntax sugar. Supports .NET Core.
Setup
public enum Gender
{
Male,
Female
}
var userIds = 0;
var testUsers = new Faker<User>()
//Optional: Call for objects that have complex initialization
.CustomInstantiator(f => new User(userIds++, f.Random.Replace("###-##-####")))
//Basic rules using built-in generators
.RuleFor(u => u.FirstName, f => f.Name.FirstName())
.RuleFor(u => u.LastName, f => f.Name.LastName())
.RuleFor(u => u.Avatar, f => f.Internet.Avatar())
.RuleFor(u => u.UserName, (f, u) => f.Internet.UserName(u.FirstName, u.LastName))
.RuleFor(u => u.Email, (f, u) => f.Internet.Email(u.FirstName, u.LastName))
//Use an enum outside scope.
.RuleFor(u => u.Gender, f => f.PickRandom<Gender>())
//Use a method outside scope.
.RuleFor(u => u.CartId, f => Guid.NewGuid());
Generate
var user = testUsers.Generate();
Console.WriteLine(user.DumpAsJson());
/* OUTPUT:
{
"Id": 0,
"FirstName": "Audrey",
"LastName": "Spencer",
"FullName": "Audrey Spencer",
"UserName": "Audrey_Spencer72",
"Email": "Audrey82@gmail.com",
"Avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/itstotallyamy/128.jpg",
"Gender": 0,
"CartId": "863f9462-5b88-471f-b833-991d68db8c93", ....
Without Fluent Syntax
public void Without_Fluent_Syntax()
{
var random = new Bogus.Randomizer();
var lorem = new Bogus.DataSets.Lorem();
var o = new Order()
{
OrderId = random.Number(1, 100),
Item = lorem.Sentence(),
Quantity = random.Number(1, 10)
};
o.Dump();
}
/* OUTPUT:
{
"OrderId": 61,
"Item": "vel est ipsa",
"Quantity": 7
} */
I tried AutoFixture (https://github.com/AutoFixture/AutoFixture) and it worked for me very well. It can easilty generate an object with a deep hierarchy of children in one line of code.
NBuilder is a very good fluent-API library for generating data. It uses rules that you define and isn't "random" per se. You may be able to randomize the inputs to the API, though, to suit your needs.
Since this still gets some attention I think it's worth mentioning the project is now available through NuGet (https://www.nuget.org/packages/NBuilder/) as well, though it hasn't been modified since 2011.
I've recently been working on one that is exactly like what you described (maybe it's been done before but this seemed like a fun project to try). It is still a work in progress but I think it captures all the features you mentioned. You can find the Nuget package here:
https://www.nuget.org/packages/randomtestvalues
And the repository here: https://github.com/RasicN/random-test-values
I hope you like it.
Example code:
var randomMyClass = RandomValue.Object<MyClass>();
AutoPoco has some of that functionality, it doesn't do it with reflection, you tell it what type of data to populate. So if you're writing unit tests, you could do it in your [Setup]
or [TestInitialize]
method.
NBuilder is pretty nice.
I believe it uses reflection as well.
Redgate makes a tool called SQL Data Generator. If you are willing to use a database as a seed for your testing objects, I think you'll find it is a pretty flexible tool.
PM> Install-Package NBuilder
note: EducationInformation class itself have lots of string properties
var rootObject = new RootObject()
{
EducationInformation = Builder<EducationInformation>.CreateNew().Build(),
PersonalInformation = Builder<PersonalInformation>.CreateNew().Build(),
PositionsInformation = Builder<PositionsInformation>.CreateNew().Build()
};
sample final JSON output: all with property name and a number
"graduateDegree":"graduateDegree1","academicDiscipline":"academicDiscipline1"
note: i do not know why using the following command returns null for all internal classes
RootObject rootObject = Builder<RootObject>.CreateNew().Build()
If you are using .NET, you can use FakeItEasy (GitHub), a free and open-source .NET dynamic fake framework.
And it's compatible with .NET Core.
Since some libraries are either a bit outdated or no longer under development, I have created my own library Oxygenize, which enables you to populate classes with either random or customized data.
RandomPOCOGenerator is a simple reflection-based tool designed for generating and populating objects with random values
[TestMethod]
public void GenerateTest()
{
RPGenerator gen = new RPGenerator();
int maxRecursionLevel = 4;
var intRes = gen.Generate<int>(maxRecursionLevel);
var stringArrayRes = gen.Generate<string[]>(maxRecursionLevel);
var charArrayRes = gen.Generate<char[]>(maxRecursionLevel);
var pocoRes = gen.Generate<SamplePocoClass>(maxRecursionLevel);
var structRes = gen.Generate<SampleStruct>(maxRecursionLevel);
var pocoArray = gen.Generate<SamplePocoClass[]>(maxRecursionLevel);
var listRes = gen.Generate<List<SamplePocoClass>>(maxRecursionLevel);
var dictRes = gen.Generate<Dictionary<string, List<List<SamplePocoClass>>>>(maxRecursionLevel);
var parameterlessList = gen.Generate<List<Tuple<string, int>>>(maxRecursionLevel);
// Non-generic Generate
var stringArrayRes = gen.Generate(typeof(string[]), maxRecursionLevel);
var pocoRes = gen.Generate(typeof(SamplePocoClass), maxRecursionLevel);
var structRes = gen.Generate(typeof(SampleStruct), maxRecursionLevel);
Trace.WriteLine("-------------- TEST Results ------------------------");
Trace.WriteLine(string.Format("TotalCountOfGeneratedObjects {0}", gen.TotalCountOfGeneratedObjects));
Trace.WriteLine(string.Format("Generating errors {0}", gen.Errors.Count));
}
Easy and clean:
public static void populateObject( object o)
{
Random r = new Random ();
FieldInfo[] propertyInfo = o.GetType().GetFields();
for (int i = 0; i < propertyInfo.Length; i++)
{
FieldInfo info = propertyInfo[i];
string strt = info.FieldType.Name;
Type t = info.FieldType;
try
{
dynamic value = null;
if (t == typeof(string) || t == typeof(String))
{
value = "asdf";
}
else if (t == typeof(Int16) || t == typeof(Int32) || t == typeof(Int64))
{
value = (Int16)r.Next(999);
info.SetValue(o, value);
}
else if (t == typeof(Int16?))
{
Int16? v = (Int16)r.Next(999);
info.SetValue(o, v);
}
else if (t == typeof(Int32?))
{
Int32? v = (Int32)r.Next(999);
info.SetValue(o, v);
}
else if (t == typeof(Int64?))
{
Int64? v = (Int64)r.Next(999);
info.SetValue(o, v);
}
else if (t == typeof(DateTime) || t == typeof(DateTime?))
{
value = DateTime.Now;
info.SetValue(o, value);
}
else if (t == typeof(double) || t == typeof(float) || t == typeof(Double))
{
value = 17.2;
info.SetValue(o, value);
}
else if (t == typeof(char) || t == typeof(Char))
{
value = 'a';
info.SetValue(o, value);
}
else
{
//throw new NotImplementedException ("Tipo não implementado :" + t.ToString () );
object temp = info.GetValue(o);
if (temp == null)
{
temp = Activator.CreateInstance(t);
info.SetValue(o, temp);
}
populateObject(temp);
}
}
catch (Exception ex)
{
}
}
}
精彩评论