Laravel测试
- Laravel 5.4.24
测试前的准备
安装Laravel
composer create-project laravel/laravel testing-laravel
安装依赖
composer require mockery/mockery --dev
修改配置
修改 phpunit.xml
定义测试数据库
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
使用
sqlite
的连接方式,使用memory
进行数据存储。
针对Model进行测试
测试前的准备
- 建立数据库模型和数据库迁移文件
php artisan make:model Article -m
- 编辑迁移文件
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->timestamps();
});
}
- 修改ModelFactory
文件在databases\factories\ModelFactory.php
$factory->define(App\Article::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'body' => $faker->sentence,
];
});
- 修改模型文件
namespace App;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
// 定义使用 __construct($data) 或 create($data) 时,可以被修改的字段,从而保证其他字段不被修改
protected $fillable = ['title', 'body'];
}
新增并修改测试文件
- 测试有没有文章
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ArticleTest extends TestCase
{
use DatabaseMigrations;
/** @test */
public function the_articles_is_empty_result()
{
// 取得所有文章
$articles = Article::all();
// 确认 $articles 是 Collection
$this->assertInstanceOf(Collection::class, $articles);
// 而文章数量为 0
$this->assertCount(0, $articles);
}
}
- 测试新增数据并列出数据
use App\Article;
class ArticleTest extends TestCase
{
// ...
/** @test */
public function the_articles_create_and_list_the_data()
{
// 新增 10 条记录
for ($i = 1; $i <= 10; $i++) {
factory(Article::class,10)->make([
'name' => 'name ' . $i,
'body' => 'body ' . $i
]);
}
// 确认数据库中有10条记录
$articles = Article::all();
$this->assertCount(10, $articles);
}
}
在实际使用Laravel项目中,我们常常不会直接通过Controller向模型获取数据,而是会使用到Repository的开发模式,那么如何测试Repository呢?
使用Repository模式
新建Repository文件
app/Repositories/ArticleRepository.php
<?php
namespace App\Repositories;
/**
* Class ArticleRepository
* @package App\Repositories
* @method latest($limit)
* @method create($attributes = array())
*/
class ArticleRepository
{
}
先建立一个空的Repository文件,后期在测试的过程中添加方法。
建立Repository测试文件
测试Repository查询
- 建立文件并编写测试代码,文件在
tests/Feature/ArticleRepositoryTest.php
<?php
namespace Tests\Feature;
use App\Article;
use App\Repositories\ArticleRepository;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ArticleRepositoryTest extends TestCase
{
use DatabaseMigrations;
/**
* @var ArticleRepository
*/
protected $repository;
protected function setUp()
{
parent::setUp();
// 填充数据
$this->repository = new ArticleRepository();
}
// 测试获取最后的10条资料
/** @test */
public function fetch_latest_10_articles()
{
// given data.
for ($i = 1; $i <= 100; $i++) {
factory(Article::class)->create([
'name' => 'name ' . $i,
'body' => 'body ' . $i,
]);
}
// 从 repository 中取得最新 10 条数据
$articles = $this->repository->latest(10)->get();
$this->assertCount(10, $articles);
// 确认标题是从 100 .. 91 倒数
// "title 100" .. "title 91"
$i = 10;
/** @var \App\Article[] $articles */
foreach ($articles as $article) {
$this->assertEquals('name ' . $i, $article->name);
--$i;
}
}
}
- 抛出错误并修复
Error: Call to undefined method App\Repositories\ArticleRepository::latest()
- 先向Repository中添加
latest()
方法
public function latest10()
{
}
执行phpunit报错。
Error: Call to a member function get() on null
- 再向Repository添加
latest()
方法
/**
* @param int $limit
* @return ArticleRepository|\Illuminate\Database\Eloquent\Builder
*/
public function latest($limit)
{
return Article::query()->orderBy('id', 'desc')->limit($limit);
}
此时测试通过。
测试Repository添加操作
- 编写测试代码
/** @test */
public function create_article()
{
$article = $this->repository->create([
'name' => 'name',
'body' => 'body',
]);
$this->assertEquals(1, $article->id);
}
抛出如下错误:
Error: Call to undefined method App\Repositories\ArticleRepository::create()
- 修改Repository中代码,新增
create()
方法:
use App\Article;
public function create()
{
}
抛出如下错误:
ErrorException: Trying to get property of non-object
- 修改Repository中
create()
方法,添加逻辑代码:
use App\Article;
/**
* Create new data.
* @param array $attributes
* @return mixed
*/
public function create(array $attributes = array())
{
return Article::create($attributes);
}
以上测试过程即为TDD测试流程