PHPUnit 问题断言模拟是使用 Laravel 的 ReflectionProperty 对象
Posted
技术标签:
【中文标题】PHPUnit 问题断言模拟是使用 Laravel 的 ReflectionProperty 对象【英文标题】:PHPUnit issue asserting mock is a ReflectionProperty object using Laravel 【发布时间】:2015-11-06 18:40:05 【问题描述】:我是 phpUnit 的新手,正在尝试设置我的第一个测试。它失败并显示以下错误消息
无法断言 ReflectionProperty Object (...) 是“Illuminate\Database\Eloquent\Model”类的实例。
本质上,我试图模拟一个模型的创建,我将其注入构造函数并通过反射测试它是正确的类型。我正在遵循这篇文章/答案中提出的建议:
How do I test this class using phpunit?
如果有人能给我一些指导,那将不胜感激。
正在测试的类在这里:
<?php
namespace PlaneSaleing\Repo\Listing;
use Illuminate\Database\Eloquent\Model;
class EloquentListing implements ListingInterface
protected $advert;
public function __construct(Model $advert)
$this->advert = $advert;
/**
* Get paginated listings
*
* @param int Current page
* @param int Number of listings per page
* @return StdClass object with $items and $totalItems for pagination
*/
public function byPage($page=1, $limit=10)
$result = new \StdClass;
$result->page = $page;
$result->limit = $limit;
$result->totalItems = 0;
$result->items = array();
$listings = $this->advert
->orderBy('created_at')
->skip( $limit * ($page-1) )
->take($limit)
->get();
// Create object to return data useful for pagination
$result->items = $listings->all();
$result->totalItems = $this->totalListings();
return $result;
服务商在这里:
<?php
namespace PlaneSaleing\Repo;
use Illuminate\Support\ServiceProvider;
use PlaneSaleing\Repo\Listing\EloquentListing as Listing;
use \Advert;
class RepoServiceProvider extends ServiceProvider
public function register()
$this->app->bind('PlaneSaleing\Repo\Listing\ListingInterface', function($app)
$app->make(Listing(new Advert));
);
我的测试在这里:
<?php
use \Mockery;
use \ReflectionClass;
use PlaneSaleing\Repo\Listing\EloquentListing;
class EloquentListingTest extends \TestCase
/**
* Testing if __constructor is setting up property
*/
public function testModelSetsUp()
$mock1 = Mockery::mock(Illuminate\Database\Eloquent\Model::class);
$listing = new EloquentListing($mock1);
$reflection = new ReflectionClass($listing);
// Making your attribute accessible
$property1 = $reflection->getProperty('advert');
$property1->setAccessible(true);
$this->assertInstanceOf(Illuminate\Database\Eloquent\Model::class, $property1);
【问题讨论】:
【参考方案1】:断言时,应该使用反射属性的实际值,而不是属性本身:
public function testModelSetsUp()
$mock1 = Mockery::mock(Illuminate\Database\Eloquent\Model::class);
$listing = new EloquentListing($mock1);
$reflection = new ReflectionClass($listing);
// Making your attribute accessible
$property1 = $reflection->getProperty('advert');
$property1->setAccessible(true);
$this->assertInstanceOf(
Illuminate\Database\Eloquent\Model::class,
$property1->getValue($listing)
);
但是,您可以大大简化测试:
public function testModelSetsUp()
$mock1 = Mockery::mock(Illuminate\Database\Eloquent\Model::class);
$listing = new EloquentListing($mock1);
$this->assertAttributeInstanceOf(
Illuminate\Database\Eloquent\Model::class,
'advert',
$listing
);
更好的是,您可以使用有意义的变量名称,使用有意义的测试方法名称,而不仅仅是断言$advert
属性是Illuminate\Database\Eloquent\Model
的一个实例,而实际上是相同 实例传递给构造函数:
public function testConstructorSetsAdvert()
$advert = Mockery::mock(Illuminate\Database\Eloquent\Model::class);
$listing = new EloquentListing($advert);
$this->assertAttributeSame(
$advert,
'advert',
$listing
);
【讨论】:
以上是关于PHPUnit 问题断言模拟是使用 Laravel 的 ReflectionProperty 对象的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Codeception 功能测试中使用 PHPUnit 断言方法?