2013-07-16 16 views
5

Come si modifica il metodo di creazione AutoFixture per float, double e decimal, in modo che quando questi tipi vengono creati avranno anche un resto?Autofixture: crea un float, doppio o decimale con il resto

Attualmente lo faccio, ma questo genera un'eccezione.

var fixture = new Fixture(); 
fixture.Customize<double>(sb => sb.FromFactory<double>(d => d * 1.33)); //This should add remainder 
var value = fixture.Create<double>(); 

risposta

6

Il tentativo di ridefinire un tipo (double) utilizzando un valore di lo stesso tipo (double) produrrà infatti una ricorsione infinita. Tuttavia, puoi farlo facilmente modificando l'input seme in un altro tipo, ad es. un int:

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

Doppio ora tendono ad avere valori frazionari troppo.

+0

Immagino di non aver mai pensato a come le cose funzionano in background e che la personalizzazione stava creando una ricorsione infinita. Grazie per aver chiarito questo! – Rok

+0

+1 È abbastanza carino! :) –

5

Una possibilità è quella di utilizzare una consuetudine ISpecimenBuilder:

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

Il RandomDoublePrecisionFloatingPointSequenceGenerator potrebbe apparire come di seguito:

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); 
     } 
    } 
} 
+0

Nikos ringrazia per l'aiuto, ma la risposta di Mark è più in linea con quello che stavo cercando. – Rok

+1

+1 Qualche motivo per rendere questo thread SpecimenBuilder sicuro - lo fai per tutti i builder? (Capisco perché un Random abbia bisogno di essere guardato bit non mi è mai venuto in mente di aggiungere questa protezione in un SpecimenBuilder.Non direi mai che di Fixture e/o Generatori che emanano dallo stesso sono garantiti come thread-safe. dato il lavoro di Immutability di ploeh in V3.0, potrebbe essere relativamente facile da ottenere). O ho perso un post sul blog: P –

+0

+1 Questo potrebbe funzionare anche senza la sicurezza del thread. Quasi tutti i generatori di sequenze numeriche sono comunque thread-safe. La maggior parte di essi (se non tutti) sono stati creati prima del 3.0. –