bchavez / Bogus

:card_index: A simple fake data generator for C#, F#, and VB.NET. Based on and ported from the famed faker.js.
Other
8.84k stars 501 forks source link

Resuing data when using CustomInstantiator #321

Closed baharedankoyuncu closed 4 years ago

baharedankoyuncu commented 4 years ago

Version Information

Software Version(s)
Bogus NuGet Package 30.0.4
.NET Core? 3.1
.NET Full Framework?
Windows OS? 10
Linux OS?
Visual Studio? 2019 v. 16.6.5

What locale are you using with Bogus?

Default

What's the problem?

I can't seem to figure out how I would be able to do custom object construction while being able to reuse some of the generated data.

Do you have sample code to show what you're trying to do?

Using the following syntax .RuleFor(u => u.Email, (f, u) => f.Internet.Email(u.FirstName, u.LastName)) it's possible to reuse the generated data e.g. u.FirstName and u.LastName when generating u.Email.

Is that possible when using CustomInstantiator?

As the below sample tries to demonstrate, how can I for instance reuse f.Internet.ExampleEmail()?

            var memberFaker = new Faker<Member>()
                .CustomInstantiator(f => new Member(
                    f.Random.Guid().ToString("N"),
                    nameFaker,
                    f.Date.Between(new DateTime(1950, 3, 9), new DateTime(2010, 4, 2)),
                    addressFaker,
                    phoneNumberFaker,
                    f.Internet.ExampleEmail(),
                    CreateAppUser(f.Internet.ExampleEmail()).Id, // How to reuse the exact same email as generated above?
                    f.PickRandom(unions),
                    unions.First().Id, // How to retrieve the union picked above? 
                    f.Random.ReplaceNumbers("######"),
                    f.Rant.Random.Words(5)
                    ));

            var testMembers = memberFaker.GenerateBetween(40, 100);
bchavez commented 4 years ago

Hello and thank you for posting your question. You can convert your lambda expression into a statement lambda to store intermediate state as shown below:

[Fact]
public void reuse_data_from_custom_instantiator()
{
   var unions = new[]
      {
         new Union("Married"),
         new Union("Single"),
         new Union("Divorced"),
      };

   var memberFaker = new Faker<Member>()
      .CustomInstantiator(f =>
         {
            //Store intermediate state here.
            var email = f.Internet.ExampleEmail();
            var selectedUnion = f.PickRandom(unions);

            return new Member(
               f.Random.Guid().ToString("N"),
               f.Name.FullName(),
               f.Date.Between(new DateTime(1950, 3, 9), new DateTime(2010, 4, 2)),
               f.Address.FullAddress(),
               f.Phone.PhoneNumber(),
               email,
               CreateAppUser(email).Id,
               selectedUnion,
               selectedUnion.Id,
               f.Random.ReplaceNumbers("######"),
               f.Rant.Random.Words(5)
            );
         });

   var testMembers = memberFaker.GenerateBetween(4, 10);
   console.Dump(testMembers);
}
private AppUser CreateAppUser(string email)
{
   return new AppUser(email);
}

public class AppUser
{
   public AppUser(string email)
   {
      this.Email = email;
      this.Id = $"appuser_id:{this.Email.ToLower()}";
   }

   public string Email { get; set; }

   public string Id { get; set; }
}

public class Union
{
   public Union(string description)
   {
      this.Description = description;
      this.Id = $"union_id:{this.Description.ToLower()}";
   }

   public string Description { get; set; }

   public string Id { get; set; }
}

public class Member
{
   public string Id { get; }
   public string Name { get; }
   public DateTime Dob { get; }
   public string Address { get; }
   public string Phone { get; }
   public string Email { get; }
   public string AppUserId { get; }
   public Union Union { get; }
   public string UnionId { get; }
   public string Code { get; }
   public string Description { get; }

   public Member(
      string id,
      string name,
      DateTime dob,
      string address,
      string phone,
      string email,
      string appUserId,
      Union union,
      string unionId,
      string code,
      string description)
   {
      this.Id = id;
      this.Name = name;
      this.Dob = dob;
      this.Address = address;
      this.Phone = phone;
      this.Email = email;
      this.AppUserId = appUserId;
      this.Union = union;
      this.UnionId = unionId;
      this.Code = code;
      this.Description = description;
   }
}

OUTPUT

[
  {
    "Id": "a8c4e3d7179655f2b265c859bda5cdf4",
    "Name": "Laurence Bogan",
    "Dob": "1991-04-21T05:27:14.1506036",
    "Address": "2316 Kristian Neck, Cummerataside, Venezuela",
    "Phone": "798-578-4250",
    "Email": "Rashawn62@example.org",
    "AppUserId": "appuser_id:rashawn62@example.org",
    "Union": {
      "Description": "Married",
      "Id": "union_id:married"
    },
    "UnionId": "union_id:married",
    "Code": "411312",
    "Description": "Bedfordshire Louisiana payment Turnpike synthesize"
  },
  {
    "Id": "d525c76edac09d7a9f230da8749cb727",
    "Name": "Zoey Hyatt",
    "Dob": "1968-07-25T08:03:13.5478003",
    "Address": "9010 Marks Wall, Lake Gabeburgh, Colombia",
    "Phone": "(316) 587-4319 x8273",
    "Email": "Lillie87@example.net",
    "AppUserId": "appuser_id:lillie87@example.net",
    "Union": {
      "Description": "Divorced",
      "Id": "union_id:divorced"
    },
    "UnionId": "union_id:divorced",
    "Code": "686599",
    "Description": "action-items Down-sized Berkshire Skyway grey"
  },
  ...
]

Hope that helps!

Thanks, Brian