2017-10-25 2 views
0

Angenommen, ich zwei Objekte mit folgenden Struktur:Vergleich Objekte mit Datetime-Eigenschaften in PHPUnit

class Item { 
    public $id; 
    public $date; 
} 

In einem Gerät zu testen, würde Ich mag die Gleichheit der beiden Elemente testen. Z.B .:

class MyTests extends PHPUnit\Framework\TestCase 
{ 
    public function testDummy() { 
     $item1 = new Item(); 
     $item1->id = 1000; 
     $item1->date = new DateTimeImmutable('now'); 

     $item2 = new Item(); 
     $item2->id = 1000; 
     $item2->date = $item1->date->modify('+1 second'); 

     // For my use case, I'd consider these two items equal. 
     $this::assertEquals($item1, $item2); // FAILURE :(
} 

Gibt es eine saubere/einfache Art und Weise, diese Objekte zu vergleichen, und ein Delta im Fall verwenden PHPUnit ein DateTime Objekt trifft?

Ich weiß, ich kann $this::assertEquals($item1->date, $item2->date, '', 10) verwenden, aber mit meinem Objekt würde ich lieber keine Aussagen für jede Eigenschaft schreiben.

Danke!

+0

Wie sind die beiden Instanzen gleich? Die Eigenschaft "Datum" liegt eine Sekunde auseinander. Was bedeutet "gleich" für Ihren Anwendungsfall? – ishegg

+0

Warum fügst du eine Sekunde hinzu und denkst sogar, dass es gleich ist? In DateTime gibt es Millisekunden. – DanFromGermany

+0

Der Fall, den Sie als Beispiel verwenden, ist nicht einmal sinnvoll, natürlich sind die Inhalte von zwei Objekten gleich, wenn Sie sie gleich setzen. Wenn du mehr Komfort willst, dann schaue ich mir 'Reflection' an. – DanFromGermany

Antwort

0

$ item1 = Datum ('D, d M Y');

$ item2 = Datum ('D, d M Y', strtotime ("+ 1 Tag"));

versuchen diese

0

nicht sicher, was die Basis von der Art des [Testergebnis] sein müssen Sie für diesen bestimmten Testfall. Aber wenn Sie testen wollen, wenn beide Objekte gleich sind:

  • die beiden Objekte vergleichen basiert auf seiner [Instanz]
  • Wenn es einen Fall, das ist eine Eigenschaft verwendet, die [Datetime] Objekt

Dann würde ich das ff vorschlagen. Behauptungen:

class MyTests extends PHPUnit\Framework\TestCase 
{ 
    public function testDummy() { 
     $item1 = new Item(); 
     $item1->id = 1000; 
     $item1->date = new DateTimeImmutable('now'); 

     $item2 = new Item(); 
     $item2->id = 1000; 
     $item2->date = $item1->date->modify('+1 second'); 

     // Option 1: Check if given object is an instance of [Item] class 
     $this::assertEquals($item1 instanceof Item, $item2 instanceof Item); 

     // Option 2: Check if given property for each assigned variables is an instance of [DateTimeImmutable] class 
     $this::assertEquals($item1->date instanceof DateTimeImmutable, $item2->date instanceof DateTimeImmutable); 
    } 
} 

Hoffe, dass dies Sie gut führen wird.

0

Ich würde vorschlagen, eine equals Methode in Ihrer Item Klasse zu implementieren und testen nur für den Rückgabewert in Ihrem Test wie folgt aus:

class MyTests extends PHPUnit\Framework\TestCase 
{ 
    public function testDummy() { 
     $item1 = new Item(); 
     $item1->id = 1000; 
     $item1->date = new DateTimeImmutable('now'); 

     $item2 = new Item(); 
     $item2->id = 1000; 
     $item2->date = $item1->date->modify('+1 second'); 

     $this->asserTrue($item1->equals($item2)); 
     $this->asserTrue($item2->equals($item1)); 
    } 
} 

für eine Item ähnlich wie diese:

class Item 
{ 
    const OFFSET_TOLERANCE = 1; 

    public $id; 
    public $date; 

    public function equals(self $item): bool 
    { 
     // in case the id is relevant as well 
     if ($this->id !== $item->id) { 
      return false; 
     } 

     // not sure how you prefer to handle the following 2 cases 
     if (null === $item->date && null === $this->date) { 
      return true; 
     } 

     if (!($this->date instanceof DateTimeInterface) || 
      !($item->date instanceof DateTimeInterface)) 
     { 
      return false; 
     } 

     $interval = $this->date->diff($item->date); 

     // note that you can also use $interval->f 
     // to compare microseconds since PHP 7.1 
     return $interval->s > self::OFFSET_TOLERANCE; 
    } 
} 

Leider gibt es keine __equals Methode wie in Java. Die einzige alternative Lösung, die ich mir vorstellen kann, ist die Implementierung einer __toString Methode, die einen irgendwie repräsentativen Wert Ihres Item Objekts zurückgibt, der den Zeitstempel ohne die letzte Ziffer enthält.

Aber in Bezug auf Lesbarkeit und Zuverlässigkeit und um sicherzustellen, dass Sie explizit über Ihre Implementierung sind, empfehle ich, für eine Lösung ähnlich dem obigen Beispiel zu gehen.