Bogus faked data: Conditional and random in the same field, possibly leaving a null faked data
Asked Answered
T

1

6

In using .net Bogus github repository for filling up a database, I would like to both fill a field randomly with something like:

{ "Mother", "Sister", "Brother", "Father", "Uncle","Niece","Nephew","Cousin"}

But also randomly leave occasional nulls too?

I have tried chaining them together but it doesn't seem like there is a syntax that the compiler likes.

                .RuleFor(u => u.Gender, f => f.PickRandom<Gender>().ToString())
                .RuleFor(u => u.BirthDate, f => f.Date.PastOffset(60,
                    DateTime.Now.AddYears(-18)).Date.ToShortDateString())
                .RuleFor(u => u.FirstName, (f, u) => f.Name.FirstName(ReturnGenderType(u.Gender)))
                .RuleFor(u => u.MiddleName, (f, u) => f.Name.FirstName(ReturnGenderType(u.Gender)))
                .RuleFor(u => u.LastName, (f, u) => f.Name.LastName(ReturnGenderType(u.Gender)))
                .RuleFor(u => u.Salutation, (f, u) => f.Name.Prefix(ReturnGenderType(u.Gender)))

 private static Bogus.DataSets.Name.Gender ReturnGenderType(string genderString)
        {
            if (genderString == "Male")
            {
                return Bogus.DataSets.Name.Gender.Male;
            }
            else
            {
                return Bogus.DataSets.Name.Gender.Female;
            }
        }

In this example it looks like it might have to be an extension as the Gender type feeds back later into the sane but random names later.

Tratner answered 28/4, 2019 at 21:42 Comment(0)
S
12

If you want Bogus to generate "sometimes null" values in rules, you can use the convenient .OrNull() extension method. The following example shows to generate nullable values with a 20% probability:

void Main()
{
   var userFaker = new Faker<User>()
            .RuleFor( u => u.FirstName, f => f.Name.FirstName())
            .RuleFor( u => u.LastName, f => f.Name.LastName().OrNull(f, .2f) );

   userFaker.Generate(10).Dump();
}

public class User{
   public string FirstName{get;set;}
   public string LastName{get;set;}
}

You can also remove the ReturnGenderType helper method and use the f => f.Person property instead. Summing it all up, here's how your code cleans up:

void Main()
{
   var userFaker = new Faker<User>()
    .RuleFor(u => u.Gender,     f => f.Person.Gender.ToString())
    .RuleFor(u => u.BirthDate,  f => f.Date.PastOffset(60, DateTime.Now.AddYears(-18)).Date.ToShortDateString())
    .RuleFor(u => u.FirstName,  f => f.Person.FirstName)
    .RuleFor(u => u.MiddleName, f => f.Name.FirstName(f.Person.Gender).OrNull(f, .2f))
    .RuleFor(u => u.LastName,   f => f.Person.LastName)
    .RuleFor(u => u.Salutation, f => f.Name.Prefix(f.Person.Gender));

   userFaker.Generate(10).Dump();
}

public class User
{
   public string Gender { get; set; }
   public string BirthDate { get; set; }
   public string FirstName { get; set; }
   public string MiddleName { get; set; }
   public string LastName { get; set; }
   public string Salutation { get; set; }
}

BTW, the Salutation generated by f.Name.Prefix(Gender) is sometimes not right because gender prefixes are not separated in the en locale. If this is a concern, you can extend Bogus a tiny bit more with an extension method that fixes your locale:

public static class MyExtensionsForBogus{
   public static string Prefix2(this Bogus.DataSets.Name name, Gender gender)
   {
      if (gender == Gender.Male)
      {
         return name.Random.ArrayElement(new[] { "Mr.", "Dr." });
      }
      return name.Random.ArrayElement(new[]{"Miss", "Ms.", "Mrs."});
   }
}

Then, the new Salutation rule becomes:

    .RuleFor(u => u.Salutation, f => f.Name.Prefix2(f.Person.Gender));

And now ya got some nice looking data there:

Hope that helps! =)

Sarsenet answered 21/6, 2019 at 6:40 Comment(6)
Is there a way to set the odds of a null differently than the odds of gender?Tratner
@user2206142 Edited answer. Yes, .OrNull has an extra parameter that controls the weight of nullability. For example, .OrNull(f, 0.7f) for a 70% probability of producing null.Sarsenet
Exactly what I needed. Thanks!Tratner
I know you say the word extension many times, but as someone just starting .NET/C# , you need to add using Bogus.Extensions; at the top of your code so OrNull() works.I am an idiot and just spent an hour trying to figure out why it didn't work.Thimbleweed
I'll consider adding .OrNull() to the root using Bogus namespace.Sarsenet
@CullenD that's why you need to use JetBrains Rider (they figure out the usings for you) :)Unhandy

© 2022 - 2024 — McMap. All rights reserved.