2014-06-06 28 views
8

Kitaplığı çalışmıyor "2. *"
PHP sürümü: PHP 5.4.24 (cli)PHPUnit Mock S3Client iyi

composer.json

{ 
    "require": { 
     "php": ">=5.3.1", 
     "aws/aws-sdk-php": "2.*", 
     ... 
    }, 

    "require-dev": { 
     "phpunit/phpunit": "4.1", 
     "davedevelopment/phpmig": "*", 
     "anahkiasen/rocketeer": "*" 
    }, 
    ... 
} 

İşlevsel eylemleri almak için bir AwsWrapper hazırladık: uploadFile, deleteFile ...
Sınıfı, test edilecek ünite bağımlılık enjeksiyonu ile okuyabilirsiniz.
Yapıcıya ve iç $ this-> s3Client-> putObject (...) dosyasına odaklanın uploadFile işlevi çağrısı.

<?php 

namespace app\lib\modules\files; 

use Aws\Common\Aws; 
use Aws\S3\Exception\S3Exception; 
use Aws\S3\S3Client; 
use core\lib\exceptions\WSException; 
use core\lib\Injector; 
use core\lib\utils\System; 

class AwsWrapper 
{ 

    /** 
    * @var \core\lib\Injector 
    */ 
    private $injector; 

    /** 
    * @var S3Client 
    */ 
    private $s3Client; 

    /** 
    * @var string 
    */ 
    private $bucket; 

    function __construct(Injector $injector = null, S3Client $s3 = null) 
    { 
    if($s3 == null) 
    { 
     $aws = Aws::factory(dirname(__FILE__) . '/../../../../config/aws-config.php'); 
     $s3 = $aws->get('s3'); 
    } 
    if($injector == null) 
    { 
     $injector = new Injector(); 
    } 
    $this->s3Client = $s3; 
    $this->bucket = \core\providers\Aws::getInstance()->getBucket(); 
    $this->injector = $injector; 
    } 

    /** 
    * @param $key 
    * @param $filePath 
    * 
    * @return \Guzzle\Service\Resource\Model 
    * @throws \core\lib\exceptions\WSException 
    */ 
    public function uploadFile($key, $filePath) 
    { 
    /** @var System $system */ 
    $system = $this->injector->get('core\lib\utils\System'); 
    $body = $system->fOpen($filePath, 'r'); 
    try { 
     $result = $this->s3Client->putObject(array(
     'Bucket' => $this->bucket, 
     'Key' => $key, 
     'Body' => $body, 
     'ACL' => 'public-read', 
    )); 
    } 
    catch (S3Exception $e) 
    { 
     throw new WSException($e->getMessage(), 201, $e); 
    } 

    return $result; 
    } 

} 

test dosyası bizim Enjektör ve PHPUnit MockObject olarak S3Client kopyası olur. S3Client ile alay etmek için, orijinal oluşturucuyu Mock Builder ile devre dışı bırakmalıyız.

$this->s3Client = $this->getMockBuilder('Aws\S3\S3Client')->disableOriginalConstructor()->getMock(); 

S3Exception atmak putObject ile test etmek iç putObject çağrısı (vaka yapılandırmak için ama biz $ this-> returnValue (beklenen $) ile aynı sorun var

:

S3Client alay etmek.

public function setUp() 
    { 
    $this->s3Client = $this->getMockBuilder('Aws\S3\S3Client')->disableOriginalConstructor()->getMock(); 
    $this->injector = $this->getMock('core\lib\Injector'); 
    } 

    public function configureSut() 
    { 
    return new AwsWrapper($this->injector, $this->s3Client); 
    } 

çalışmıyor kodu:

Testi Class ve yapılandırmak SUT init için

Test işlevimizi yürüttüğümüzde, enjekte edilen S3Client istisnayı alamaz veya beklenen değeri döndürmez, her zaman NULL değerini döndürür.

xdebug ile S3Client MockObject öğesinin doğru yapılandırıldığını gördük ancak will() öğesinde yapılandırıldığı gibi çalışmıyor. Bir "çözüm" (veya kötü bir çözüm) bir S3ClientWrapper yapıyor olabilir, bu yalnızca sorunu, alaylarla test edilemeyen diğer Sınıflara taşıyacaktır.

Herhangi bir fikrin var mı?

GÜNCELLEME Xdebug ile yapılandırmak MockObject üzerinde Ekran Görüntüsü: enter image description here

cevap

10

Aşağıdaki kod çalışır ve beklendiği gibi, bu yüzden PHPUnit veya AWS SDK kaynaklanan sınırlamalara içine çalıştıran sanmıyorum geçer. Sadece tepkisini taklit istiyor ve/alay nesneleri stubbing umurumda değil eğer

<?php 

namespace Aws\Tests; 

use Aws\S3\Exception\S3Exception; 
use Aws\S3\S3Client; 
use Guzzle\Service\Resource\Model; 

class MyTest extends \PHPUnit_Framework_TestCase 
{ 
    public function testMockCanReturnResult() 
    { 
     $model = new Model([ 
      'Contents' => [ 
       ['Key' => 'Obj1'], 
       ['Key' => 'Obj2'], 
       ['Key' => 'Obj3'], 
      ], 
     ]); 

     $client = $this->getMockBuilder('Aws\S3\S3Client') 
      ->disableOriginalConstructor() 
      ->setMethods(['listObjects']) 
      ->getMock(); 
     $client->expects($this->once()) 
      ->method('listObjects') 
      ->with(['Bucket' => 'foobar']) 
      ->will($this->returnValue($model)); 

     /** @var S3Client $client */ 
     $result = $client->listObjects(['Bucket' => 'foobar']); 

     $this->assertEquals(
      ['Obj1', 'Obj2', 'Obj3'], 
      $result->getPath('Contents/*/Key') 
     ); 
    } 

    public function testMockCanThrowException() 
    { 
     $client = $this->getMockBuilder('Aws\S3\S3Client') 
      ->disableOriginalConstructor() 
      ->setMethods(['getObject']) 
      ->getMock(); 
     $client->expects($this->once()) 
      ->method('getObject') 
      ->with(['Bucket' => 'foobar']) 
      ->will($this->throwException(new S3Exception('VALIDATION ERROR'))); 

     /** @var S3Client $client */ 
     $this->setExpectedException('Aws\S3\Exception\S3Exception'); 
     $client->getObject(['Bucket' => 'foobar']); 
    } 
} 

Ayrıca Guzzle MockPlugin kullanabilirsiniz.

+0

-> setMethods (['putObject']) çalışıyor! Teşekkürler!! –