GenericRandom, create a POCO with random values

Why do we need this

In unit or integration tests we often need to create input with data. For example if you test a mapper, all properties of the input must have a value. It will save time if most of the properties are filled in with values automatically.

This can also be used on other scenario's.


[Fact]
public void OrderSender_ShouldSendToCorrectPerson()
{
    var genericRandom = new GenericRandom(0);
    // Create a Person with random property values.
    var person = genericRandom.Next<Person>(); 
    var target = new OrderSender();

    var sendResult = target.SendTo(person);

    sendResult.Name.Should().Be(person.Name);
}

Same seed results in same random values

Just like the .NET Random class, you get the same values if you start with the same seed. That helps to prevent flaky tests (= fails sometimes but not always).

You can use a different seed to get different results, but always the same different results.

How does that POCO with random values looks like?

Imagine, you have a POCO like this:


public class Person
{
    public string Name { get; set; }
    public int SingleNumber { get; set; }
    public Person Child { get; set; }
    public DateTime SomeDate { get; set; }
    public List<long> MultipleNumbers { get; set; }
}

You will always get the same values as proofed in these tests:


[Fact]
public void ClassTest_ForPerson_ShouldHaveValuesAtHighestLevel()
{
    var target = new GenericRandom(0);

    var actual = target.Next<Person>();

    actual.Should().NotBeNull();
    actual.Name.Should().Be("txvhMh4a");
    actual.SingleNumber.Should().Be(97979476);
    actual.SomeDate.Should().Be(new DateTime(2000,4,22, 16, 7, 16));
    actual.MultipleNumbers.Should().Equal(new List<long>{ 81528902 , 40344430, 51148790, 23214253 });
}

[Fact]
public void ClassTest_ForPerson_ShouldHave3Levels()
{
    var target = new GenericRandom(0);

    var actual = target.Next<Person>();

    actual.Should().NotBeNull();
    actual.Name.Should().Be("txvhMh4a");

    actual.Child.Should().NotBeNull();
    actual.Child.Name.Should().Be("RScmc9B2");
    
    actual.Child.Child.Should().NotBeNull();
    actual.Child.Child.Name.Should().Be("pTxz9Brf");

    // Maximum 3 levels deep to prevent a stack overflow
    actual.Child.Child.Child.Should().BeNull(); 
}

[Fact]
public void ClassTest_ForString_ShouldHaveSemiRandomResults()
{
    var target = new GenericRandom(0);

    var actual1 = target.Next<string>();
    actual1.Should().Be("txvhMh4a");

    // Second call for the same type gives a different result
    var actual2 = target.Next<string>();
    actual2.Should().Be("RScmc9B");
}

How to use GenericRandom in your project?

The code of the GenericRandom class can be found on Github. If you use .Net 6, you can also use the Q11.Tools Nuget package..

Leave a Comment

Comment

Comments