SyntaxHighlighter

About Me

2016年7月14日 星期四

Laravel PhpUnit 關閉 middleware

Laravel Unit test 筆記

Laravel PhpUnit 關閉 middleware

方法一

  • 修改 route 取 middle ware 的方式

於使用 middleware 之前加上

// app/Http/route.php

$middleware = [ ];
if ( !App::runningUnitTests() ) {
    $middleware[] = 'api.auth';
}

$api->version( 'v1', function ( $api )  use ($middleware){
    $api->get( '/users/me', ['middleware' => $middleware,
        'uses' => '\App\Http\Controllers\UserController@currentUser'
     ]);
});

Ref: https://github.com/dingo/api/issues/571#issuecomment-129939376

方法二

  • 於 test case 中加上 use WithoutMiddleware

透過這個方式也會跳過 middleware

<?php

    use Illuminate\Foundation\Testing\WithoutMiddleware;
    use Illuminate\Foundation\Testing\DatabaseMigrations;
    use Illuminate\Foundation\Testing\DatabaseTransactions;

    class ExampleTest extends TestCase
    {
        use WithoutMiddleware;
        
        public function test_example() {
                ...
        }
    }

Ref: https://laravel.com/docs/5.1/testing#application-testing

2016年7月5日 星期二

Mockery 筆記

前言

Mockery 在 UnitTest 上非常常見,需要去模擬第三方套件的時候就會需要用到他,舉例來說像是 PHPMailer ,頭痛的地方有幾點

  1. 寫測試但不希望他寄信
  2. 我該怎麼去模擬他的 method 讓結果跟測試期望的一樣

為了 Coverage 100% 這時候就推薦使用 Mockery 了。

使用 Mockery

安裝套件

composer require --dev mockery/mockery

程式邏輯

  1. overwrite PHPMailer 並 mock 每個使用到的 method
  2. 實作 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
  3. (重要)測試單元最後需ㄧㄠ透過 $this->tearDown() 去 reset mockery

案例分享

Mian Class - Main.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

參考資料