库:"aws/aws-sdk-php":"2.*"
PHP版本:PHP 5.4.24(cli)
composer.json
{ "require": { "php": ">=5.3.1", "aws/aws-sdk-php": "2.*", ... }, "require-dev": { "phpunit/phpunit": "4.1", "davedevelopment/phpmig": "*", "anahkiasen/rocketeer": "*" }, ... }
我们已经制作了一个AwsWrapper来获取功能操作:uploadFile,deleteFile ...
你可以阅读这个类,依赖注入要进行单元测试.
专注于构造函数和内部$ this-> s3Client-> putObject(...)调用uploadFile函数.
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; } }
测试文件将我们的Injector和S3Client实例作为PhpUnit MockObject.要模拟S3Client,我们必须使用Mock Builder禁用原始构造函数.
要模拟S3Client:
$this->s3Client = $this->getMockBuilder('Aws\S3\S3Client')->disableOriginalConstructor()->getMock();
要配置内部putObject调用(使用putObject测试的情况抛出S3Exception,但我们在$ this-> returnValue($ expected)中遇到了同样的问题.
要初始化测试类并配置sut:
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); }
不工作的代码:
$expectedArray = array( 'Bucket' => Aws::getInstance()->getBucket(), 'Key' => $key, 'Body' => $body, 'ACL' => 'public-read', ); $this->s3Client->expects($timesPutObject) ->method('putObject') ->with($expectedArray) ->will($this->throwException(new S3Exception($exceptionMessage, $exceptionCode))); $this->configureSut()->uploadFile($key, $filePath);
当我们执行我们的测试函数时,注入的S3Client不会抛出异常或返回预期值,总是返回NULL.
使用xdebug,我们已经看到S3Client MockObject配置正确但不能按照will()配置的方式工作.
一个"解决方案"(或一个糟糕的解决方案)可能正在执行S3ClientWrapper,这只会将问题转移到无法使用模拟进行单元测试的其他类.
任何的想法?
UPDATE使用xdebug配置MockObject的屏幕截图:
以下代码按预期工作和传递,因此我认为您不会遇到由PHPUnit或AWS SDK引起的任何限制.
<?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']); } }
如果你只是想模拟响应并且不关心模拟/存根对象,你也可以使用Guzzle MockPlugin.