PHP birim test DataStores

1 Cevap php

Ben phpunit kullanarak ama zor o datastore'una olarak kullanılan nesneler için iyi mocks ve taslakları oluşturmak yapmak bulabilirsiniz ediyorum.

Örnek:

class urlDisplayer {
    private $storage;
    public function __construct(IUrlStorage $storage) { $this->storage = $storage; }
    public function displayUrl($name) {}
    public function displayLatestUrls($count) {}
}

interface IUrlStorage {
    public function addUrl($name, $url);
    public function getUrl($name);
}

class MysqlUrlStorage implements IUrlStorage {
    // saves and retrieves from database
}

class NonPersistentStorage implements IUrlStorage {
    // just stores for this request
}

Örneğin ne kadar farklı $ adlarında iki çağrılarda birden fazla olası değeri dönen PHPUnit taslakları var?

Edit: örnek testi:

public function testUrlDisplayerDisplaysLatestUrls {
    // get mock storage and have it return latest x urls so I can test whether
    // UrlDisplayer really shows the latest x
}

Bu testte alay ancak belgelerinde Ben sadece nasıl bir değer döndürmek için, URL'ler bir dizi dönmelidir.

1 Cevap

Sorunuz çok net değil - ama farklı durumlarda farklı bir değer döndürmek için phpunit ait sahte nesneleri kullanmak nasıl soruyorsunuz varsayıyorum?

Ne yapabileceğini hemen hemen sınırsızdır -: phpunit ait sahte sınıfları, özel bir işlev (bir geri çağırma işlevi / yöntem yani) belirtmek sağlar.

Aşağıdaki örnekte, ben onun depolama denir, her zaman bir sonraki url dönecektir sahte IUrlStorage sınıfı oluşturuldu.

public function setUp()
{
    parent::setUp();
    $this->fixture = new UrlDisplayer(); //change this to however you create your object

    //Create a list of expected URLs for testing across all test cases
    $this->expectedUrls = array(
          'key1' => 'http://www.example.com/url1/'
        , 'key2' => 'http://www.example.net/url2/'
        , 'key3' => 'http://www.example.com/url3/'
    );
}

public function testUrlDisplayerDisplaysLatestUrls {
    //Init        
    $mockStorage = $this->getMock('IUrlStorage');
    $mockStorage->expects($this->any())
        ->method('getUrl')
        ->will( $this->returnCallback(array($this, 'mockgetUrl')) );

    reset($this->expectedUrls); //reset array before testing

    //Actual Tests
    $this->assertGreaterThan(0, count($this->expectedUrls));
    foreach ( $this->expectedUrls as $key => $expected ) {
        $actual = $this->fixture->displayUrl($key);
        $this->assertEquals($expected, $actual);
    }
}

public function mockGetUrl($name)
{
    $value = current($this->expectedUrls);
    next($this->expectedUrls);

    //Return null instead of false when end of array is reached
    return ($value === false) ? null : $value;
}


Alternatif olarak, bazen sadece gerekli işlevini alay gerçek bir sınıf oluşturmak daha kolaydır. Bu iyi tanımlanmış ve küçük arayüzleri ile özellikle kolaydır.

Bu özel durumda, bunun yerine aşağıda sınıfını kullanarak öneririm:

class MockStorage implements IUrlStorage
{
    protected $urls = array();

    public function addUrl($name, $url)
    {
        $this->urls[$name] = $url;
    }

    public function getUrl($name)
    {
        if ( isset($this->urls[$name]) ) {
            return $this->urls[$name];
        }
        return null;
    }
}
?>

Sonra birim test sınıfında sadece aşağıdaki gibi fikstür örneğini:

public function setUp() {
   $mockStorage = new MockStorage();

   //Add as many expected URLs you want to test for
   $mockStorage->addUrl('name1', 'http://example.com');
   //etc...

   $this->fixture = new UrlDisplayer($mockStorage);
}