用随机数据填充对象的C#库
本文关键字:对象 填充 随机 数据 | 更新日期: 2023-09-27 18:01:29
我想用随机数据填充我的对象(用于测试目的(,有库可以做到吗?
某种反射方法,它将遍历对象图并初始化基元属性,如(string、int、DateTime等((但要深入执行,包括集合、子对象等(
转向架
Bogus是一个用于C#和.NET的简单而合理的伪数据生成器。faker.js的C#端口,其灵感来自FluentValidation的语法糖支持.NET核心
设置
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());
生成
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", ....
没有流利的语法
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
} */
NBuilder是一个非常好的用于生成数据的fluent-API库。它使用你定义的规则,而不是"随机"的本质。不过,你可以随机输入API,以满足你的需求。
由于这仍然受到一些关注,我认为值得一提的是,该项目现在可以通过NuGet获得(https://www.nuget.org/packages/NBuilder/)同样,尽管自2011年以来一直没有修改。
我试过AutoFixture(https://github.com/AutoFixture/AutoFixture)它对我很有效。它可以很容易地在一行代码中生成一个具有深层子层次结构的对象。
我最近正在做一个与您描述的完全相同的项目(也许以前也做过,但这似乎是一个有趣的项目(。这项工作仍在进行中,但我认为它涵盖了您提到的所有功能。你可以在这里找到Nuget包:
https://www.nuget.org/packages/randomtestvalues
这里的存储库:https://github.com/RasicN/random-test-values
我希望你喜欢。
示例代码:
var randomMyClass = RandomValue.Object<MyClass>();
AutoPoco有一些这样的功能,它不使用反射,而是告诉它要填充什么类型的数据。因此,如果您正在编写单元测试,可以在[Setup]
或[TestInitialize]
方法中进行。
NBuilder非常不错。
我相信它也使用反射。
Redgate制作了一个名为SQL数据生成器的工具。如果你愿意使用数据库作为测试对象的种子,我想你会发现它是一个非常灵活的工具。
PM> Install-Package NBuilder
注意:EducationInformation类本身有很多字符串属性
var rootObject = new RootObject()
{
EducationInformation = Builder<EducationInformation>.CreateNew().Build(),
PersonalInformation = Builder<PersonalInformation>.CreateNew().Build(),
PositionsInformation = Builder<PositionsInformation>.CreateNew().Build()
};
示例最终JSON输出:全部带有属性名和数字
"graduateDegree":"graduateDegree1","academicDiscipline":"academicDiscipline1"
注意:我不知道为什么使用以下命令会为所有内部类返回null
RootObject rootObject = Builder<RootObject>.CreateNew().Build()
如果您使用.NET,您可以使用FakeItEasy(GitHub(,这是一个免费的开源.NET动态伪造框架。
它与.NET Core兼容。
由于有些库有点过时或不再在开发中,我创建了自己的库Oxygenize,它使您能够用随机或自定义数据填充类。
[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));
}
简单清洁:
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)
{
}
}
}