2013-07-16 5 views
5

Wie ändere ich AutoFixture create-Methode für float, double und decimal, so dass wenn diese Typen erstellt werden sie auch einen Rest haben?Autoftixture - Erstellen Sie einen Float, double oder decimal mit Rest

Momentan mache ich das, aber dies löst Ausnahme aus.

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

Antwort

6

Der Versuch, durch Verwendung eines Wertes einen Typ (double) neu zu definieren, von derselbe Typ (double) wird tatsächlich eine unendliche Rekursion ergeben. Sie können dies jedoch leicht durchführen, indem Sie die Saateingabe in einen anderen Typ ändern, z. ein int:

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

Doubles werden nun neigen dazu, zu Bruchwert zu haben.

+0

Ich denke, ich habe nicht wirklich darüber nachgedacht, wie die Dinge im Hintergrund funktionieren und dass die Anpassung eine unendliche Rekursion erzeugt. Danke für die Klärung! – Rok

+0

+1 Das ist ziemlich ordentlich! :) –

5

Eine Möglichkeit ist, eine benutzerdefinierte zu verwenden ISpecimenBuilder:

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

Die RandomDoublePrecisionFloatingPointSequenceGenerator wie folgt aussehen könnte:

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 danke für die Hilfe, aber Marks Antwort ist mehr inline mit dem, was ich suchte. – Rok

+1

+1 Jeder Grund, diesen SpecimenBuilder Thread sicher zu machen - tun Sie das für alle Ihre Erbauer? (Ich verstehe, warum ein Random bewacht werden muss, aber es ist mir nie in den Sinn gekommen, dieses Guarding in einem SpecimenBuilder hinzuzufügen. Ich würde nie von Fixture und/oder Generatoren ausgehen, die garantiert sicher sind. Ich kann sicherlich verstehen, wie, vor allem gegeben @ ploehs Unveränderlichkeit arbeiten in V3.0, dass es relativ einfach sein könnte, zu erreichen). Oder habe ich einen Blogpost verpasst: P –

+0

+1 Dieser könnte auch ohne die Fadensicherheit funktionieren. Fast alle numerischen Sequenzgeneratoren sind jedoch Thread-sicher. Die meisten von ihnen (wenn nicht alle) wurden vor 3.0 erstellt. –

Verwandte Themen