前言
Mockery 在 UnitTest 上非常常見,需要去模擬第三方套件的時候就會需要用到他,舉例來說像是 PHPMailer ,頭痛的地方有幾點- 寫測試但不希望他寄信
- 我該怎麼去模擬他的 method 讓結果跟測試期望的一樣
為了 Coverage 100% 這時候就推薦使用 Mockery 了。
使用 Mockery
安裝套件
composer require --dev mockery/mockery
程式邏輯
- overwrite PHPMailer 並 mock 每個使用到的 method
- 實作 AddAddress, isHTML, Send 這三個 method
- AddAddress 參數說明
- shouldReceive: 需要去 mock 的 method
- atLeast: 這個 method 至少會執行幾次
- times(n): 執行 n 次,需搭配 atLeast 去使用
- withAnyArgs: 沒有限制他的傳入值
- isHTML 參數說明
- once: 只會被執行一次
- with(true): 只會帶入 true
- Send 參數說明
- andReturn(true): 只會 return true
- (重要)測試單元最後需ㄧㄠ透過 $this->tearDown() 去 reset mockery
案例分享
Mian Class - Main.php
Unit Test - MyTest.php
ps. 依照各自環境的狀況自己去 require autoload.php
class Main { protected $mail; function __construct() { $this->PHPMailerInit(); } public function run() { /* * Main function ......... */ $this->mail->Body = $html; if (!$this->mail->Send()) { return false; } return true; } protected function PHPMailerInit() { /* phpmailer */ $this->mail = new \PHPMailer; $this->mail->CharSet = 'UTF-8'; $this->mail->From = 'sender@test.com'; $this->mail->AddAddress('hashman@test.com'); $this->mail->AddAddress('andy@test.com'); $this->mail->isHTML(true); $this->mail->Subject = 'My subject'; } }
Unit Test - MyTest.php
use \Mockery as m; class MyTest extends PHPUnit_Framework_TestCase { public function setUp() { $this->setUpDb(); $this->mockData(); } public function testMailWillSend() { $mock = m::mock('overload:\PHPMailer'); $mock->shouldReceive('AddAddress') ->atLeast() ->times(1) ->withAnyArgs(); $mock->shouldReceive('isHTML') ->once() ->with(true); $mock->shouldReceive('Send') ->andReturn(true); $main = new Main(); $result = $main->run(); $this->assertEquals(true, $result, 'Email 寄出應該要回傳 true'); $this->tearDown(); } public function testMailWontSend() { $mock = m::mock('overload:\PHPMailer'); $mock->shouldReceive('AddAddress') ->atLeast() ->times(1) ->withAnyArgs(); $mock->shouldReceive('isHTML') ->once() ->with(true); $mock->shouldReceive('Send') ->andReturn(false); $main = new Main(); $result = $main->run(); $this->assertEquals(false, $result, 'Email 無法寄出應該要回傳 false'); $this->tearDown(); } protected function tearDown() { m::close(); } }
ps. 依照各自環境的狀況自己去 require autoload.php
參考資料
Mockery Github - https://github.com/padraic/mockery
Mockery Docs(Mocking hard Dependencies) - http://docs.mockery.io/en/latest/cookbook/mocking_hard_dependencies.html
Mockery Docs( 參數說明 ) - http://docs.mockery.io/en/latest/reference/expectations.html
沒有留言:
張貼留言