问题
I am using Laravel 4.2 and am trying to get into using phpunit to test my code rather than manually test everything. I have read Jeffrey Way's book 'Laravel Testing Decoded' but I still finding my very first test tricky. The class I am trying to test is below. What I am struggling with is - what should I test?
I don't think I should test the database or the Model $advert as these should have their own tests. In which case I think I need to either mock $advert or create a factory for it but I don't know which.
Any pointers would be greatly appreciated.
EloquentListing.php
<?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->totalArticles;
return data;
}
/**
* Get total listing count
*
*
*/
protected function totalArticles()
{
return $this->advert->count();
}
}
回答1:
You have to test every method you have in your class. You have constructor, which should be also tested, to see, if it sets model to your attributes, as well your protected method.
You should mock your model with mockery. It can be installed with
$ composer require mockery/mockery
Then in your test file:
<?php
use Mockery;
use ReflectionClass;
use PlaneSaleing\Repo\Listing\EloquentListing;
class EloquentListingTest extends \TestCase
{
/**
* Testing if __constructor is setting up property
*/
public function testModelSetsUp()
{
$mock = Mockery::mock(Illuminate\Database\Eloquent\Model::class);
$listing = new EloquentListing($mock);
$reflection = new ReflectionClass($listing);
// Making your attribute accessible
$property = $reflection->getProperty('advert');
$property->setAccessible(true);
$this->assertInstanceOf(Illuminate\Database\Eloquent\Model::class, $property);
}
/**
* Here you will check if your model is recieving calls
*/
public function testByPage()
{
$mock = Mockery::mock(Illuminate\Database\Eloquent\Model::class);
$mock->shouldReceive('orderBy')
->with('created_at')
->once()
->andReturn(Mockery::self())
->shouldReceive('skip')
->with(10)
->once()
->andReturn(Mockery::self())
->shouldReceive('take')
->with(10)
->andReturn(Mockery::self())
->shouldReceive('get')
->once()
->andReturn(Mockery::self())
->shouldReceive('all')
->once()
->andReturn(Mockery::self());
$listing = new EloquentListing($mock);
}
/**
* Here you will see, if your model is receiving call '->count()'
*/
public function testTotalArticles()
{
$mock = Mockery::mock(Illuminate\Database\Eloquent\Model::class);
$mock->shouldReceive('count')
->once()
->andReturn(Mockery::self());
$listing = new EloquentListing($mock);
// We will have to set method accesible
$reflection = new ReflectionClass($listing);
$method = $reflection->getMethod('totalArticles');
$method->setAccessible(true);
$listing->totalArticles();
}
}
来源:https://stackoverflow.com/questions/31893619/how-do-i-test-this-class-using-phpunit