用随机数据填充对象的C#库

本文关键字:对象 填充 随机 数据 | 更新日期: 2023-09-27 18:01:29

我想用随机数据填充我的对象(用于测试目的(,有库可以做到吗?

某种反射方法,它将遍历对象图并初始化基元属性,如(string、int、DateTime等((但要深入执行,包括集合、子对象等(

用随机数据填充对象的C#库

转向架

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,它使您能够用随机或自定义数据填充类。

RandomPOCOGenerator是一个简单的基于反射的工具,用于生成和填充具有随机值的对象
[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)
            {
            }
        }
    }