5

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.

SuperDave
  • 373
  • 5
  • 14

1 Answers1

9

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! =)

Brian Chavez
  • 8,048
  • 5
  • 54
  • 47
  • Is there a way to set the odds of a null differently than the odds of gender? – SuperDave Jun 21 '19 at 10:14
  • @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. – Brian Chavez Jun 21 '19 at 16:30
  • Exactly what I needed. Thanks! – SuperDave Jun 23 '19 at 12:28
  • 1
    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. – Cullen D Nov 16 '21 at 18:35
  • 1
    I'll consider adding `.OrNull()` to the root `using Bogus` namespace. – Brian Chavez Nov 18 '21 at 22:52
  • @CullenD that's why you need to use JetBrains Rider (they figure out the usings for you) :) – TimB Jul 07 '22 at 21:46