# 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()
```
1. 先向Repository中添加`latest()`方法
```
public function latest10()
{
}
```
> 执行phpunit报错。
> `Error: Call to a member function get() on null`
2. 再向Repository添加`latest()`方法
```
/**
* @param int $limit
* @return ArticleRepository|\Illuminate\Database\Eloquent\Builder
*/
public function latest($limit)
{
return Article::query()->orderBy('id', 'desc')->limit($limit);
}
```
> 此时测试通过。
#### 测试Repository添加操作
1. 编写测试代码
```
/** @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()
```
2. 修改Repository中代码,新增`create()`方法:
```
use App\Article;
public function create()
{
}
```
抛出如下错误:
```
ErrorException: Trying to get property of non-object
```
3. 修改Repository中`create()`方法,添加逻辑代码:
```
use App\Article;
/**
* Create new data.
* @param array $attributes
* @return mixed
*/
public function create(array $attributes = array())
{
return Article::create($attributes);
}
```
> 以上测试过程即为TDD测试流程
## Reference
[Web Development with Laravel 5](https://gist.github.com/jaceju/c415c1b42daf4c589f2a)
- 介绍
- Laravel5发送邮件使用Service隔离业务
- 如何使用Repository模式
- 如何使用Service模式
- 如何使用Presenter模式
- Laravel 5.* 执行迁移文件报错:Specified key was too long error
- EloquentORM关联关系
- EloquentORM关联关系之一对一
- EloquentORM关联关系之一对多
- EloquentORM关联关系之远层一对多
- EloquentORM关联关系之多对多
- EloquentORM关联关系之多态关联
- EloquentORM关联关系之多对多多态关联
- Laravel测试
- Laravel中涉及认证跳转地址的修改的地方
- Laravel中Collection的基本使用
- all
- avg
- chuck
- collapse
- combine
- contains
- containsStrict
- count
- diff
- diffAssoc
- diffKeys
- each
- every
- except
- filter
- first
- flatMap
- flatten
- flip
- forget
- forPage
- get
- groupBy
- has
- implode
- intersect
- intersectKey
- isEmpty
- isNotEmpty
- keyBy
- keys
- last
- map
- mapWithKeys
- max
- median
- merge
- min
- mode
- nth
- only
- partition
- pipe
- pluck
- pop
- prepend
- pull
- push
- put
- random
- reduce
- reject
- reverse
- search
- shift
- shuffle
- slice
- sort
- sortBy
- sortByDesc
- splice
- split
- sum
- take
- tap
- times
- toArray
- toJson
- transform
- union
- unique
- uniqueStrict
- values
- when
- where
- whereStrict
- whereIn
- whereInStrict
- whereNotIn
- whereNotInStrict
- zip
- Laravel中Collection的实际使用
- collection中sum求和
- collection格式化计算数据
- collection格式化计算数据计算github事件得分总和
- collection格式化markdown数据列表
- collection格式化计算两个数组的数据
- collection中reduce创建lookup数组
- TODO