# 模擬器
- [介紹](#introduction)
- [事件](#mocking-events)
- [任務](#mocking-jobs)
- [Facades](#mocking-facades)
<a name="introduction"></a>
## 介紹
測試 Laravel 應用時,有時候你可能想要「模擬」實現應用的部分功能的行為,從而避免該部分在測試過程中真正執行。例如,控制器執行過程中會觸發一個事件( Events ),你想要模擬這個事件的監聽器,從而避免該事件在測試這個控制器時真正執行。如上可以讓你僅測試控制器的 HTTP 響應情況,而不用去擔心觸發事件。當然,你可以在單獨的測試中測試該事件的邏輯。
Laravel 針對事件、任務和 facades 的模擬提供了開箱即用的輔助函數。這些輔助函數基于 Mockery 封裝而成,使用非常簡單,無需你手動調用復雜的 Mockery 函數。當然,你也可以使用 [Mockery](http://docs.mockery.io/en/latest/) 或者 PHPUnit 創建自己的模擬器。
<a name="mocking-events"></a>
## 事件
如果在你的項目中大量使用了 Laravel 的事件系統,那你可能經常會希望在測試過程中禁用特定的事件。比如,測試用戶注冊時并不想觸發 `UserRegistered` 事件,此類事件的常見行為包括發送「歡迎」郵件等。
Laravel 提供了一個非常方便的方法 `expectsEvents` ,可以用來阻止觸發特定事件,而不影響其他事件:
<?php
use App\Events\UserRegistered;
class ExampleTest extends TestCase
{
/**
* 測試用戶注冊
*/
public function testUserRegistration()
{
$this->expectsEvents(UserRegistered::class);
// Test user registration...
}
}
你也可以使用 `doesntExpectEvents` 函數來驗證事件確定沒有被觸發:
<?php
use App\Events\OrderShipped;
use App\Events\OrderFailedToShip;
class ExampleTest extends TestCase
{
/**
* 測試訂單發貨
*/
public function testOrderShipping()
{
$this->expectsEvents(OrderShipped::class);
$this->doesntExpectEvents(OrderFailedToShip::class);
// 測試訂單發貨...
}
}
如果你想阻止所有事件的觸發,可以使用 `withoutEvents` 方法。該方法調用后,所有事件觸發事件都將被模擬器捕獲:
<?php
class ExampleTest extends TestCase
{
public function testUserRegistration()
{
$this->withoutEvents();
// 測試用戶注冊的代碼...
}
}
<a name="mocking-jobs"></a>
## 任務
有些時候,在測試應用程序的一些請求時,可能會希望測試指定任務是否已經發送。上述做法可以對你的控制器進行隔離測試,無需在意任務處理器的邏輯。當然,你可以在單獨的測試中測試這個任務處理器。
Laravel 提供了一個非常方便的方法 `expectsJobs` ,可以用來驗證指定任務是否已被發送。當然,這個任務不會被執行:
<?php
class App\Jobs\ShipOrder;
class ExampleTest extends TestCase
{
public function testOrderShipping()
{
$this->expectsJobs(ShipOrder::class);
// 訂單發貨的測試...
}
}
> {note} 這個方法只能檢測到通過 `DispatchesJobs` trait 的輔助函數 `dispatch` 發送的任務,檢測不到使用 `Queue::push` 直接發送到隊列的任務。
與事件的模擬器輔助函數類似,你可以使用 `doesntExpectJobs` 方法來確定指定任務是否沒有被發送:
<?php
class App\Jobs\ShipOrder;
class ExampleTest extends TestCase
{
/**
* 測試訂單取消操作
*/
public function testOrderCancellation()
{
$this->doesntExpectJobs(ShipOrder::class);
// 測試訂單取消操作...
}
}
或者,你可以使用 `withoutJobs` 方法阻止發送所有任務。在測試中調用此方法后,當前測試中所有任務都會被丟棄:
<?php
class App\Jobs\ShipOrder;
class ExampleTest extends TestCase
{
/**
* 測試訂單取消操作
*/
public function testOrderCancellation()
{
$this->withoutJobs();
// 測試訂單取消操作...
}
}
<a name="mocking-facades"></a>
## Facades
不像傳統的靜態函數調用, [facades](/docs/{{version}}/facades) 是可以被模擬的,相對靜態函數來說這是個巨大的優勢,即使你在使用依賴注入,測試時依然會非常方便。在很多測試中,你可能經常想在控制器中模擬對 Laravel facade 的調用。比如下面控制器中的行為:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
/**
* 顯示網站的所有用戶
*
* @return Response
*/
public function index()
{
$value = Cache::get('key');
//
}
}
我們可以通過 `shouldReceive` 方法模擬 `Cache` facade ,此函數會返回一個模擬器 ( [Mockery](https://github.com/padraic/mockery) ) 實例,由于對 facade 的調用實際上都是由 Laravel 的 [service container](/docs/{{version}}/container) 管理的,所以 facade 能比傳統的靜態類表現出更好的測試便利性。如下,我們來模擬一下 `Cache` facade `get` 方法的行為:
<?php
class FooTest extends TestCase
{
public function testGetIndex()
{
Cache::shouldReceive('get')
->once()
->with('key')
->andReturn('value');
$this->visit('/users')->see('value');
}
}
> {note} 不可以模擬 `Request` facade ,測試時,如果需要定制傳遞的數據請使用 HTTP 輔助函數,例如 `call` 和 `post`。
## 譯者署名
| 用戶名 | 頭像 | 職能 | 簽名 |
|---|---|---|---|
| [@zhwei](https://github.com/zhwei) | <img class="avatar-66 rm-style" src="https://avatars3.githubusercontent.com/u/1446459?v=3&s=100"> | 翻譯 | ^_^ |
| [@JobsLong](https://phphub.org/users/56) | <img class="avatar-66 rm-style" src="https://dn-phphub.qbox.me/uploads/avatars/56_1427370654.jpeg?imageView2/1/w/100/h/100"> | Review | 我的個人主頁:[http://jobslong.com](http://jobslong.com) |
| [@summerblue](https://github.com/summerblue) | <img class="avatar-66 rm-style" src="https://avatars2.githubusercontent.com/u/324764?v=3&s=100"> | Review | A man seeking for Wisdom. |
- 說明
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- 錯誤與日志
- 開發環境
- HomeStead
- Valet
- 核心概念
- 服務容器
- 服務提供者
- 門面(facades)
- contracts
- HTTP層
- 路由
- 中間件
- CSRF保護
- 控制器
- 請求
- 響應
- Session
- 表單驗證
- 視圖與模板
- 視圖
- Blade模板
- 本地化
- Javascript與CSS
- 入門指南
- laravel-elixir
- 安全
- 用戶認證
- 用戶授權
- 重置密碼
- API授權
- 加密解密
- 哈希
- 綜合話題
- 廣播系統
- 緩存系統
- 事件系統
- 文件存儲
- 郵件發送
- 消息通知
- 隊列
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent集合
- 修改器
- 序列化
- Artisan控制臺
- Artisan 命令行
- 任務調度
- 測試
- 快速入門
- 應用程序測試
- 數據庫測試
- 模擬器
- 官方擴展包
- Cashier交易包
- Envoy 部署工具
- Passport OAuth 認證
- Scout 全文搜索
- Socialite 社交化登錄
- 附錄
- 集合
- 輔助函數
- 擴展包開發
- 交流說明