Statik Yöntem Aramalar taklit PHPUnit içinde Mock Nesneler?

6 Cevap php

Ben veri veritabanına erişimi (biliyorsunuz, CRUD, aslında) yöneten bir sınıf test etmek için çalışıyorum. Bizim kullandığımız DB kütüphanesi ilk statik bir çağrı tarafından tablo nesnesi olsun, burada bir API sahip olur:

function getFoo($id) {
  $MyTableRepresentation = DB_DataObject::factory("mytable");
  $MyTableRepresentation->get($id);
  ... do some stuff
  return $somedata
}

... Eğer fikir olsun.

Biz bu yöntemi test etmek için çalışıyorum, ancak (a) biz test için gerçek bir db bağlantısı gerekmez, ve (b) biz bile test için DB_DataObject lib eklemek gerekmez böylece DataObject şeyler alay ediyorlar .

Ancak, PHPUnit I $ this-> getMock () uygun statik bir çağrı kurmak için almak gibi olamaz. Ben var ...

        $DB_DataObject = $this->getMock('DB_DataObject', array('factory'));

... Ama test hala bilinmeyen bir yöntem "fabrika" diyor. Dedi önce DB_DataObject bulamadı çünkü o nesne oluşturma biliyorum. Şimdi bunu yapabilirsiniz. Ama, hiçbir yöntem?

Ne gerçekten yapmak istiyorum iki sahte nesneler, tablo nesne için bir sıra döndürülen sahip olmaktır. Yani, ben bu fabrika statik çağrı belirtmeniz gerekir, ama aynı zamanda bazı ben zaten kurdum diğer davalarını nesne belirtilen döndürür yapmak değil sadece.

Ben bir süre önce SimpleTest did bu (kod bulamıyorum) ve iyi çalıştı bir ihtar olarak bahsetmeliyiz.

Ne verir?

[GÜNCELLEME]

Ben beklentiden ile ilgisi vardır () olduğunu kavramak başlıyorum

6 Cevap

Ben statik bir çağrı kullanmak için değil daha iyi olacağını ikiniz de katılıyorum. Ancak, ben DB_DataObject bir üçüncü taraf kütüphane ve statik çağrı onların kod kullanımı için their en iyi uygulama, bizimki olduğunu söylemeyi unuttum sanırım. Doğrudan döndürülen nesneyi inşa dahil, nesneleri kullanmak için başka yollar vardır. Sadece yaprakları belâ o / o DB_DO sınıfını kullanarak ne olursa olsun sınıf dosyası ifadeleri gerektirir içerir. En azından ben düşünüyorum - size bu arada senin testinde aynı isimde bir sınıf taklit çalışıyorsanız testler (ya da sadece izole edilemez) kıracak çünkü berbat.

Bu kodu bir bağımlılık iyi bir örnektir - tasarım imkansız değil gerçek sınıf daha Mock enjekte yaptı.

Benim ilk önerim oldukça statik bir çağrı daha bir örneğini kullanmak için kod denemek ve refactor olacaktır.

Eğer kütüphane değiştiremez zaman, onun sizin erişimi değiştirebilir. Kodunuzda bir örnek yöntemi için DB_DataObject :: fabrika () tüm aramaları refactor:

function getFoo($id) {
  $MyTableRepresentation = $this->getTable("mytable");
  $MyTableRepresentation->get($id);
  ... do some stuff
  return $somedata
}

function getTable($table) {
  return DB_DataObject::factory($table);
}

Şimdi () Bir sahte tablo nesnesi döndürmek test ettiğiniz sınıfının kısmi alay kullanmak ve gettable olabilir.

function testMyTable() {
  $dao = $this->getMock('MyTableDao', array('getMock'));
  $table = $this->getMock('DB_DataObject', ...);
  $dao->expects($this->any())
      ->method('getTable')
      ->with('mytable')
      ->will($this->returnValue($table));
  $table->expects...
  ...test...
}

Ne eksik (veya değil?) Oluyor sizin DB_DataObject sınıfından fabrika yöntemini çağırmadan önce hazırlanmış bir db nesnesi geçirmek için bir setter olduğunu. Eğer (aynı arayüzü ile) bir alay ya da özel bir db nesne geçirebilirsiniz bu şekilde ihtiyaç doğması gerekir.

Test kurulumunda:

 public function setUp() {
      $mockDb = new MockDb();
      DB_DataObject::setAdapter($mockDb);
 }

Fabrika () yöntemi, alaya DB örneğini döndürmesi gerekir. Zaten sizin sınıfa entegre değilse, muhtemelen o iş yapmak) yöntemi de (fabrika refactor gerekir.

Eğer gerektirir / test durumunda DB_DataObject için sınıf dosyasına dahil? PHPUnit nesneyi taklit etmeye çalışır önce sınıf yoksa, bu gibi hataları alabilirsiniz.

PHPUnit MockFunction uzantı ile artı runkit da statik yöntemler taklit edebilir. Bu maymun yama ve bu nedenle yalnızca aşırı durumlarda kullanılması gerektiğini, çünkü dikkatli olun. İyi bir programlama uygulamaları yerine geçmez.

https://github.com/tcz/phpunit-mockfunction