Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofixture - create a float, double or decimal with remainder

How do I modify AutoFixture create method for float, double and decimal, so that when these types get created they will also have a remainder?

Currently I do this, but this throws exception.

var fixture = new Fixture();
fixture.Customize<double>(sb => sb.FromFactory<double>(d => d * 1.33));   //This should add remainder
var value = fixture.Create<double>();
like image 742
Rok Avatar asked Jul 16 '13 09:07

Rok


2 Answers

Attempting to redefine a type (double) by using a value of the same type (double) will, indeed, yield an infinite recursion. However, you can easily make this work by changing the seed input into another type - e.g. an int:

var fixture = new Fixture();
fixture.Customize<double>(c => c.FromFactory<int>(i => i * 1.33));
var value = fixture.Create<double>();

Doubles will now tend to have fractional values too.

like image 98
Mark Seemann Avatar answered Oct 06 '22 00:10

Mark Seemann


One option is to use a custom ISpecimenBuilder:

var fixture = new Fixture();
fixture.Customizations.Add(
    new RandomDoublePrecisionFloatingPointSequenceGenerator());

The RandomDoublePrecisionFloatingPointSequenceGenerator could look like below:

internal class RandomDoublePrecisionFloatingPointSequenceGenerator
    : ISpecimenBuilder
{
    private readonly object syncRoot;
    private readonly Random random;

    internal RandomDoublePrecisionFloatingPointSequenceGenerator()
    {
        this.syncRoot = new object();
        this.random = new Random();
    }

    public object Create(object request, ISpecimenContext context)
    {
        var type = request as Type;
        if (type == null)
            return new NoSpecimen(request);

        return this.CreateRandom(type);
    }

    private double GetNextRandom()
    {
        lock (this.syncRoot)
        {
            return this.random.NextDouble();
        }
    }

    private object CreateRandom(Type request)
    {
        switch (Type.GetTypeCode(request))
        {
            case TypeCode.Decimal:
                return (decimal)
                    this.GetNextRandom();

            case TypeCode.Double:
                return (double)
                    this.GetNextRandom();

            case TypeCode.Single:
                return (float)
                    this.GetNextRandom();

            default:
                return new NoSpecimen(request);
        }
    }
}
like image 33
Nikos Baxevanis Avatar answered Oct 05 '22 23:10

Nikos Baxevanis