Laravel 4.2一樣可以寫測試,只是有些地方要注意

Laravel 5.1內建PHPUnit與Mockery,直接使用就可以了,但Laravel 4.2沒有內建,必須自己手動安裝,但因為PHPUnit在Oct.02,2015宣布重要改版,PHPUnit 5.0僅支援PHP 5.6PHP 7,只有PHPUnit 4.x會繼續支援PHP 5.3PHP 5.4PHP 5.5,所以導致Laravel 4.2在安裝PHPUnit時在版本上需要特別注意。此外在自己新增class部分,測試上也有小雷要注意。

Version


Laravel 4.2.17
PHPUnit 4.8
Mockery 0.9.4

安裝PHPUnit


1
oomusou@mac:~/Larave42PHPUnit_demo$ composer require phpunit/phpunit:~4.0 --dev

一般我們安裝套件時,都會安裝最新版本,所以不用特別指定版本編號,但在這裡有些特別,因為Laravel 4.2要求的是PHP 5.4,而PHPUnit 5.0僅支援PHP 5.6PHP 7,所以我們在此特別只安裝PHPUnit 4.x,截止目前為止為PHPUnit 4.8

~4.0表示>= 4.0< 5.0
--dev表示安裝在composer.jsonrequire-dev區段。

安裝Mockery


1
oomusou@mac:~/Larave42PHPUnit_demo$ composer require mockery/mockery --dev

Mockery沒特別限制,安裝最新版即可。

執行PHPUnit


1
oomusou@mac:~/Larave42PHPUnit_demo$ vendor/bin/phpunit

Laravel 4.2在app/tests目錄下預設已經寫了一個testing,可直接執行。

1
PHPUnit 4.8.10 by Sebastian Bergmann and contributors.

.

Time: 2.15 seconds, Memory: 12.25Mb

OK (1 test, 1 assertion)

實際測試自己的class


app/blog/Article.php
1
2
3
4
5
6
7
namespace App\Blog;


class Article
{


}

app目錄下新增blog目錄,並新增Article class。

先寫測試


app/tests/ArticleTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use App\Blog\Article;

class ArticleTest extends TestCase
{

public function testHello()
{

// arrange
$target = new Article('Sam');
$expected = 'Hello Sam';

// act
$actual = $target->hello();

// assert
$this->assertEquals($expected, $actual);
}
}

執行測試

1
oomusou@mac:~/MyProject$ vendor/bin/phpunit
1
PHPUnit 4.8.12 by Sebastian Bergmann and contributors.

PHP Fatal error:  Class 'App\Blog\Article' not found in /Users/oomusou/MyProject/app/tests/ArticleTest.php on line 10

Fatal error: Class 'App\Blog\Article' not found in /Users/oomusou/MyProject/app/tests/ArticleTest.php on line 10

PHPUnit回報找不到Article class,明明我們class已經先建好了,這樣測試失敗並不合理。1 1這個問題在Laravel 5.1並不會出現。

修改composer.json


composer.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
"laravel/framework": "4.2.*"
},
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php",
"app/blog"
]
},
"scripts": {
"post-install-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"post-update-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"post-create-project-cmd": [
"php artisan key:generate"
]
},
"config": {
"preferred-install": "dist"
},
"minimum-stability": "stable",
"require-dev": {
"phpunit/phpunit": "~4.0",
"mockery/mockery": "^0.9.4"
}
}

17行

1
"app/blog"

由於我們自己新增了app/blog目錄,要自己在composer.jsonautoload區段補上。

對class loader最佳化


1
oomusou@mac:~/MyProject$ php artisan optimize

必須自行下php artisan optimize指令,否則PHPUnit抓不到我們自行新增的class。2 2在Laravel 5.1也不必自行下php artisan optimize指令。

1
Generating optimized class loader
Compiling common classes
Compiling views

再執行測試 :

1
PHPUnit 4.8.12 by Sebastian Bergmann and contributors.

PHP Fatal error:  Call to undefined method App\Blog\Article::hello() in /Users/oomusou/MyProject/app/tests/ArticleTest.php on line 14

Fatal error: Call to undefined method App\Blog\Article::hello() in /Users/oomusou/MyProject/app/tests/ArticleTest.php on line 14

目前已經找得到Article class,只是找不到hello(),因為我們還沒寫,所以測試失敗合理。

實現method


app/blog/Article.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace App\Blog;

class Article
{

private $name;

public function __construct($name)
{

$this->name = $name;
}

public function hello()
{

return 'Hello ' . $this->name;
}
}

再次執行測試 :

1
PHPUnit 4.8.12 by Sebastian Bergmann and contributors.

.

Time: 78 ms, Memory: 10.25Mb

OK (1 test, 1 assertion)

Conclusion


  • 雖然Laravel 4.2沒有內建PHPUnit與Mockery,但我們一樣可以寫testing,只要手動安裝PHPUnit與Mockery即可。
  • 若自行建立class,需自行在composer.json加入目錄,並執行php artisan optimize,否則PHPUnit會找不到我們新建的class。

Sample Code


完整的範例可以在我的GitHub上找到。