2012-07-28 18 views
8

VfsStream ile bir dosya sistemi işlemi (aslında php: // girişten okunan bir dosya) ile uğraşmaya çalışıyorum ancak iyi bir dokümantasyon ve örnek olmaması beni gerçekten rahatsız ediyor. aşağıdaki gibiVFSStream ile dosya sistemi işlemlerini test etmeye çalışmak

Ben test olduğum sınıftan ilgili kodudur:

class RequestBody implements iface\request\RequestBody 
{ 
    const 
     REQ_PATH = 'php://input', 

    protected 
     $requestHandle = false; 

    /** 
    * Obtain a handle to the request body 
    * 
    * @return resource a file pointer resource on success, or <b>FALSE</b> on error. 
    */ 
    protected function getHandle() 
    { 
     if (empty ($this -> requestHandle)) 
     { 
      $this -> requestHandle = fopen (static::REQ_PATH, 'rb'); 
     } 
     return $this -> requestHandle; 
    } 
} 

şöyle benim PHPUnit testinde kullanıyorum kurgusunda:

protected function configureMock() 
{ 
    $mock = $this -> getMockBuilder ('\gordian\reefknot\http\request\RequestBody'); 

    $mock -> setConstructorArgs (array ($this -> getMock ('\gordian\reefknot\http\iface\Request'))) 
      -> setMethods (array ('getHandle')); 


    return $mock; 
} 

/** 
* Sets up the fixture, for example, opens a network connection. 
* This method is called before a test is executed. 
*/ 
protected function setUp() 
{ 
    \vfsStreamWrapper::register(); 
    \vfsStream::setup ('testReqBody'); 

    $mock = $this -> configureMock(); 
    $this -> object = $mock -> getMock(); 

    $this -> object -> expects ($this -> any()) 
        -> method ('getHandle') 
        -> will ($this -> returnCallback (function() { 
         return fopen ('vfs://testReqBody/data', 'rb'); 
        })); 
} 

gerçek testte I VFS kurmak ve aşağıdaki gibi bir onaylama çalıştırmayı (ki dolaylı getHandle() tetikleyen bir yöntemini çağırdığında):

public function testBodyParsedParsedTrue() 
{ 
    // Set up virtual data 
    $fh  = fopen ('vfs://testReqBody/data', 'w'); 
    fwrite ($fh, 'test write 42'); 
    fclose ($fh); 
    // Make assertion 
    $this -> object -> methodThatTriggersGetHandle(); 
    $this -> assertTrue ($this -> object -> methodToBeTested()); 
} 

Bu sadece testin askıda kalmasına neden oluyor.

Açıkçası, burada çok yanlış bir şey yapıyorum, ancak belgelerin durumu göz önünde bulundurulduğunda, ne yapmak istediğimi anlayamıyorum. Bu vfsstream'in neden olduğu bir şey mi, yoksa buraya bakmaya ihtiyacım olan şeyle dalga geçen phpunit mi?

+0

VFSStream kullanırken

<?php //... $reqBody = "Request body contents" $vfsContainer = vfsStream::setup('testReqBody'); vfsStream::newFile('data')->at($vfsContainer)->setContent($reqBody); $this->assertSame($reqBody, file_get_contents('vfs://testReqBody/data')); 

orijinal kodundan Unutulmaması gereken bir diğer şey, vfsStreamWrapper::register(); aramaya gerek kalmamasıdır sınıf yaklaşımı Bir sarıcı için bir sarıcıdır. StreamWrapper php arayüzüne dayalı bir sınıf yazdım ve işi bitirmek için bu yeterli. Ayrıca bakınız: http://php.net/manual/en/class.streamwrapper.php – Codebeat

cevap

9

Peki ... akışlarla nasıl test edilir? Tüm vfsStream, dosya sistemi işlemleri için özel bir akış sarmalayıcısı sağlar. Tek bir akış argümanının davranışını çözmek için tam vf -Stream kütüphanesine ihtiyacınız yoktur - bu doğru bir çözüm değildir. Bunun yerine, dosya sistemi işlemleriyle uğraşmaya çalışmadığınız için kendi tek akışlı sarma düzenleyicinizi yazmanız ve kaydetmeniz gerekir. Yapmanız

class ClassThatNeedsStream { 
    private $bodyStream; 
    public function __construct($bodyStream) { 
     $this->bodyStream = $bodyStream; 
    } 
    public function doSomethingWithStream() { 
     return stream_get_contents($this->bodyStream); 
    } 
} 

Gerçek hayatta:

Eğer teste aşağıdaki basit sınıf var ki
$phpInput = fopen('php://input', 'r'); 
new ClassThatNeedsStream($phpInput); 

Yani, biz bize sağlayacak kendi akışı sarıcı oluşturmak bunu test etmek için Geçtiğimiz akışın davranışını denetleyin. Özel akış sarmalayıcıları büyük bir konu olduğundan çok fazla ayrıntıya giremiyorum. Ama temelde süreç şöyledir:

  1. Kayıt PHP
  2. Açık

Yani kayıtlı akım sarmalayıcı şemasını kullanarak bir kaynak akışı ile bu akım sarmalayıcı özel akışı sarmalayıcı

  • yaratın özel akış şu şekilde görünür:

    Ardından test durumda bu yapardın:

    public function testSomething() { 
        stream_wrapper_register('streamTest', 'TestingStreamStub'); 
        TestingStreamStub::$body = 'my custom stream contents'; 
        $stubStream = fopen('streamTest://whatever', 'r+'); 
    
        $myClass = new ClassThatNeedsStream($stubStream); 
        $this->assertEquals(
         'my custom stream contents', 
         $myClass->doSomethingWithStream() 
        ); 
    
        stream_wrapper_unregister('streamTest'); 
    } 
    

    Sonra, sadece ben akışı okumasını geri gelir hangi verileri değiştirmek için dere ambalajında ​​tanımladığınız statik özelliklerini değiştirebilir. Ya da, temel akışı sarmalayıcı sınıfınızı genişletin ve bunun yerine testler için farklı senaryolar sağlamak üzere kaydedin.

    Bu çok basit bir giriş, ancak asıl nokta şudur: gerçek dosya sistemi işlemleriyle alay etmedikçe vfsStream kullanmayın - bunun için tasarlandığı şey budur. Aksi takdirde, test için özel bir akış sarıcı yazın.

    PHP başlangıç ​​için bir prototip akım sarmalayıcı sınıf sağlar: http://www.php.net/manual/en/class.streamwrapper.php

  • +1

    Tahmin edeceğim başka bir gün için VFS'yi dışarıda bırakmam gerekecek. – GordonM

    0

    Ben benzer bir cevabı bulana mücadele - Ben belgeleri de eksik buldum.

    Ben senin sorunu vfs://testReqBody/data, varolan dosyaya bir yol değil olmasıydı şüpheli (php://input daima olacağı gibi.)

    kabul cevabı kabul edilebilir bir cevap, o zaman bu vfsStreamWrapper ile eşdeğerdir. Eğer vfsStream::setup() arayarak sonra içeriğini tanımlamak, öyle ki, bu kadar bölünmüş gerekiyorsa

    <?php 
    // ... 
    $reqBody = "Request body contents" 
    vfsStream::setup('testReqBody', null, ['data' => $reqBody]); 
    $this->assertSame($reqBody, file_get_contents('vfs://testReqBody/data')); 
    

    da yine bu nasıl. tüm alt sınıflar ve ad vb her şey OLMALIDIR ile kitinin gereksiz kompleks parça vfsStream::setup()

    İlgili konular