2016-02-09 26 views
6

私はsocialiteを利用するアプリケーションを持っていますので、Github認証のテストを作成したいのですが、Socialite Facadeを使用してSocialite driverメソッドを呼び出すのですが、私はnull型の値を取得しようとしています。以下はLaravel Socialiteをテストするには

私は

以下
public function testGithubLogin() 
{ 
    Socialite::shouldReceive('driver') 
     ->with('github') 
     ->once(); 
    $this->call('GET', '/github/authorize')->isRedirection(); 
} 

を書かれているテストは、それはSociallite::driver($provider)Laravel\Socialite\Two\GithubProviderのインスタンスを返すので、そのような結果を返す、と考えるかもしれない理由を私は理解してテスト

public function authorizeProvider($provider) 
{ 
    return Socialite::driver($provider)->redirect(); 
} 

の実装でありますこの値をインスタンス化できない場合、戻り値の型を指定することは不可能です。私はコントローラを正常にテストするのに助けが必要です。おかげ

+0

私はあなたが 'Socialite :: shouldReceive( 'driver-> redirect')'をしたいと思うと思います。 – ceejayoz

+0

@ceejayozそれは動作しません、 'ドライバ - >リダイレクト'の方法が表示されないと文句を言います –

答えて

4

両方の回答は素晴らしかったが、必須ではないコードがたくさんあり、その回答を推測することができました。

これはすべて私がする必要があります。

まず名士のユーザータイプ

$abstractUser = Mockery::mock('Laravel\Socialite\Two\User') 

第二のモックは、そのメソッドの期待値が

$abstractUser 
    ->shouldReceive('getId') 
    ->andReturn(rand()) 
    ->shouldReceive('getName') 
    ->andReturn(str_random(10)) 
    ->shouldReceive('getEmail') 
    ->andReturn(str_random(10) . '@gmail.com') 
    ->shouldReceive('getAvatar') 
    ->andReturn('https://en.gravatar.com/userimage'); 

第三に、あなたはプロバイダー/ユーザー・コール

Socialite::shouldReceive('driver->user')->andReturn($abstractUser); 
を模擬する必要がありますを呼び出して設定します

最後にあなたの主張を書いてください

$this->visit('/auth/google/callback') 
    ->seePageIs('/') 
+0

はたくさんのように見えています –

+0

たくさんありませんが、私は追加するのを忘れてしまっただけです。 –

+0

私はこの部分を理解していない 'Socialite :: shouldReceive( 'driver-> user') - > andReturn($ abstractValidUser); 'driver-> user'部分が正確になるようにします – LTroya

5
$provider = Mockery::mock('Laravel\Socialite\Contracts\Provider'); 
$provider->shouldReceive('redirect')->andReturn('Redirected'); 
$providerName = class_basename($provider); 
//Call your model factory here 
$socialAccount = factory('LearnCast\User')->create(['provider' => $providerName]); 

$abstractUser = Mockery::mock('Laravel\Socialite\Two\User'); 
// Get the api user object here 
$abstractUser->shouldReceive('getId') 
      ->andReturn($socialAccount->provider_user_id) 
      ->shouldReceive('getEmail') 
      ->andReturn(str_random(10).'@noemail.app') 
      ->shouldReceive('getNickname') 
      ->andReturn('Laztopaz') 
      ->shouldReceive('getAvatar') 
      ->andReturn('https://en.gravatar.com/userimage'); 

$provider = Mockery::mock('Laravel\Socialite\Contracts\Provider'); 
$provider->shouldReceive('user')->andReturn($abstractUser); 

Socialite::shouldReceive('driver')->with('facebook')->andReturn($provider); 

// After Oauth redirect back to the route 
$this->visit('/auth/facebook/callback') 
// See the page that the user login into 
->seePageIs('/'); 

注:useクラス

使用Laravel \名士\ファサード\名士の上部にある社交パッケージ。

私は同じ問題を抱えていましたが、上記の手法を使って解決できました。 @ceejayoz。私はこれが役立つことを願っています

4

これは難しいかもしれませんが、より読みやすいテストができると思います。うまくいけば、あなたが私が描写しようとしているものを簡略化するのを助けるでしょう。

私の考えは、httpリクエストをスタブすることです。 Facebookには、1)/oauth/access_token(アクセストークンを取得する)、2)/me(ユーザーに関するデータを取得する)の2つがあります。

  1. .envファイルに次の行を追加します)HTTPプロキシを使用するようにphp教える::そのために

    は私が一時的にvcrフィクスチャを作成するmitmproxyphpを添付

    HTTP_PROXY=http://localhost:8080 
    HTTPS_PROXY=http://localhost:8080 
    
  2. に知らせますphpプロキシの証明書は次のとおりです。openssl.cafile = /etc/php/mitmproxy-ca-cert.pemphp.iniを追加します。またはcurl.cainfoです。

  3. 再起動php-fpm
  4. 開始mitmproxy
  5. ブラウザを mitmproxyまで接続してください。
  6. 開発中のサイトにfacebook(ここではTDDなし)を使用してログインしてください。必要であればログインfacebookにリダイレクトする前に、要求(フロー)のリストをクリアするmitmproxymitmproxy < 0.18用C)で

    押しz。または、fコマンド(lmitmproxy < 0.18)とgraph.facebook.comを使用して余分なリクエストを除外します。

    twitterの場合、league/oauth1-client 1.7以上が必要です。 1つはguzzle/guzzleからguzzlehttp/guzzleに切り替えました。それ以外の場合はログインできません。

  7. mimtproxyからtests/fixtures/facebookにデータをコピーしてください。私はyamlフォーマットを使用し、ここでは次のようになります。あなたは> = 0.18 mitmproxyを持っている場合は、コマンドEを使用することができるため

    - 
        request: 
         method: GET 
         url: https://graph.facebook.com/oauth/access_token?client_id=...&client_secret=...&code=...&redirect_uri=... 
        response: 
         status: 
          http_version: '1.1' 
          code: 200 
          message: OK 
         body: access_token=...&expires=... 
    - 
        request: 
         method: GET 
         url: https://graph.facebook.com/v2.5/me?access_token=...&appsecret_proof=...&fields=first_name,last_name,email,gender,verified 
        response: 
         status: 
          http_version: '1.1' 
          code: 200 
          message: OK 
         body: '{"first_name":"...","last_name":"...","email":"...","gender":"...","verified":true,"id":"..."}' 
    

    。あるいは、コマンドPを使用してください。要求/応答をクリップボードにコピーします。 mitmproxyにファイルを保存する場合は、DISPLAY= mitmproxyで実行できます。

    ワークフロー全体をテストしているわけではないので、php-vcrの録画機能を使用する方法はありません。それと

私は、次のテストを書くことができました(はい、彼らはドットに置き換え、すべてのそれらの値と罰金です、であるようにコピーして自由に感じます)。

注記でも、備品はlaravel/socialiteのバージョンに依存します。私はFacebookに問題があった。バージョン2.0.16laravel/socialiteが開始しましたpost requestsアクセストークンを取得します。また、FacebookのURLにapi versionがあります。

これらの製品は2.0.14です。それに対処する一つの方法は、(願わくば、composerは、本番環境でrequire-devセクションに1を無視しますsocialiteは、開発環境で適切なバージョンであることを保証するために(厳密バージョン仕様に)だけでなくcomposer.jsonファイルのrequire-devセクションにlaravel/socialite依存関係を持つことです。)実稼働環境でcomposer install --no-devを実行することを考慮してください。

AuthController_HandleFacebookCallbackTest.php

<?php 

use Illuminate\Foundation\Testing\DatabaseTransactions; 
use Illuminate\Support\Facades\Auth; 
use VCR\VCR; 

use App\User; 

class AuthController_HandleFacebookCallbackTest extends TestCase 
{ 
    use DatabaseTransactions; 

    static function setUpBeforeClass() 
    { 
     VCR::configure()->enableLibraryHooks(['stream_wrapper', 'curl']) 
      ->enableRequestMatchers([ 
       'method', 
       'url', 
      ]); 
    } 

    /** 
    * @vcr facebook 
    */ 
    function testCreatesUserWithCorrespondingName() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals('John Doe', User::first()->name); 
    } 

    /** 
    * @vcr facebook 
    */ 
    function testCreatesUserWithCorrespondingEmail() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals('[email protected]', User::first()->email); 
    } 

    /** 
    * @vcr facebook 
    */ 
    function testCreatesUserWithCorrespondingFbId() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals(123, User::first()->fb_id); 
    } 

    /** 
    * @vcr facebook 
    */ 
    function testCreatesUserWithFbData() 
    { 
     $this->doCallbackRequest(); 

     $this->assertNotEquals('', User::first()->fb_data); 
    } 

    /** 
    * @vcr facebook 
    */ 
    function testRedirectsToHomePage() 
    { 
     $this->doCallbackRequest(); 

     $this->assertRedirectedTo('/'); 
    } 

    /** 
    * @vcr facebook 
    */ 
    function testAuthenticatesUser() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals(User::first()->id, Auth::user()->id); 
    } 

    /** 
    * @vcr facebook 
    */ 
    function testDoesntCreateUserIfAlreadyExists() 
    { 
     $user = factory(User::class)->create([ 
      'fb_id' => 123, 
     ]); 

     $this->doCallbackRequest(); 

     $this->assertEquals(1, User::count()); 
    } 

    function doCallbackRequest() 
    { 
     return $this->withSession([ 
      'state' => '...', 
     ])->get('/auth/facebook/callback?' . http_build_query([ 
      'state' => '...', 
     ])); 
    } 
} 

tests/fixtures/facebook

- 
    request: 
     method: GET 
     url: https://graph.facebook.com/oauth/access_token 
    response: 
     status: 
      http_version: '1.1' 
      code: 200 
      message: OK 
     body: access_token=... 
- 
    request: 
     method: GET 
     url: https://graph.facebook.com/v2.5/me 
    response: 
     status: 
      http_version: '1.1' 
      code: 200 
      message: OK 
     body: '{"first_name":"John","last_name":"Doe","email":"john.doe\u0040gmail.com","id":"123"}' 

AuthController_HandleTwitterCallbackTest.php

<?php 

use Illuminate\Foundation\Testing\DatabaseTransactions; 
use Illuminate\Support\Facades\Auth; 
use VCR\VCR; 
use League\OAuth1\Client\Credentials\TemporaryCredentials; 

use App\User; 

class AuthController_HandleTwitterCallbackTest extends TestCase 
{ 
    use DatabaseTransactions; 

    static function setUpBeforeClass() 
    { 
     VCR::configure()->enableLibraryHooks(['stream_wrapper', 'curl']) 
      ->enableRequestMatchers([ 
       'method', 
       'url', 
      ]); 
    } 

    /** 
    * @vcr twitter 
    */ 
    function testCreatesUserWithCorrespondingName() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals('joe', User::first()->name); 
    } 

    /** 
    * @vcr twitter 
    */ 
    function testCreatesUserWithCorrespondingTwId() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals(123, User::first()->tw_id); 
    } 

    /** 
    * @vcr twitter 
    */ 
    function testCreatesUserWithTwData() 
    { 
     $this->doCallbackRequest(); 

     $this->assertNotEquals('', User::first()->tw_data); 
    } 

    /** 
    * @vcr twitter 
    */ 
    function testRedirectsToHomePage() 
    { 
     $this->doCallbackRequest(); 

     $this->assertRedirectedTo('/'); 
    } 

    /** 
    * @vcr twitter 
    */ 
    function testAuthenticatesUser() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals(User::first()->id, Auth::user()->id); 
    } 

    /** 
    * @vcr twitter 
    */ 
    function testDoesntCreateUserIfAlreadyExists() 
    { 
     $user = factory(User::class)->create([ 
      'tw_id' => 123, 
     ]); 

     $this->doCallbackRequest(); 

     $this->assertEquals(1, User::count()); 
    } 

    function doCallbackRequest() 
    { 
     $temporaryCredentials = new TemporaryCredentials(); 
     $temporaryCredentials->setIdentifier('...'); 
     $temporaryCredentials->setSecret('...'); 
     return $this->withSession([ 
      'oauth.temp' => $temporaryCredentials, 
     ])->get('/auth/twitter/callback?' . http_build_query([ 
      'oauth_token' => '...', 
      'oauth_verifier' => '...', 
     ])); 
    } 
} 

tests/fixtures/twitter

- 
    request: 
     method: POST 
     url: https://api.twitter.com/oauth/access_token 
    response: 
     status: 
      http_version: '1.1' 
      code: 200 
      message: OK 
     body: oauth_token=...&oauth_token_secret=... 
- 
    request: 
     method: GET 
     url: https://api.twitter.com/1.1/account/verify_credentials.json 
    response: 
     status: 
      http_version: '1.1' 
      code: 200 
      message: OK 
     body: '{"id_str":"123","name":"joe","screen_name":"joe","location":"","description":"","profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/456\/userpic.png"}' 

AuthController_HandleGoogleCallbackTest.php

<?php 

use Illuminate\Foundation\Testing\DatabaseTransactions; 
use Illuminate\Support\Facades\Auth; 
use VCR\VCR; 

use App\User; 

class AuthController_HandleGoogleCallbackTest extends TestCase 
{ 
    use DatabaseTransactions; 

    static function setUpBeforeClass() 
    { 
     VCR::configure()->enableLibraryHooks(['stream_wrapper', 'curl']) 
      ->enableRequestMatchers([ 
       'method', 
       'url', 
      ]); 
    } 

    /** 
    * @vcr google 
    */ 
    function testCreatesUserWithCorrespondingName() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals('John Doe', User::first()->name); 
    } 

    /** 
    * @vcr google 
    */ 
    function testCreatesUserWithCorrespondingEmail() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals('[email protected]', User::first()->email); 
    } 

    /** 
    * @vcr google 
    */ 
    function testCreatesUserWithCorrespondingGpId() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals(123, User::first()->gp_id); 
    } 

    /** 
    * @vcr google 
    */ 
    function testCreatesUserWithGpData() 
    { 
     $this->doCallbackRequest(); 

     $this->assertNotEquals('', User::first()->gp_data); 
    } 

    /** 
    * @vcr google 
    */ 
    function testRedirectsToHomePage() 
    { 
     $this->doCallbackRequest(); 

     $this->assertRedirectedTo('/'); 
    } 

    /** 
    * @vcr google 
    */ 
    function testAuthenticatesUser() 
    { 
     $this->doCallbackRequest(); 

     $this->assertEquals(User::first()->id, Auth::user()->id); 
    } 

    /** 
    * @vcr google 
    */ 
    function testDoesntCreateUserIfAlreadyExists() 
    { 
     $user = factory(User::class)->create([ 
      'gp_id' => 123, 
     ]); 

     $this->doCallbackRequest(); 

     $this->assertEquals(1, User::count()); 
    } 

    function doCallbackRequest() 
    { 
     return $this->withSession([ 
      'state' => '...', 
     ])->get('/auth/google/callback?' . http_build_query([ 
      'state' => '...', 
     ])); 
    } 
} 

tests/fixtures/google

- 
    request: 
     method: POST 
     url: https://accounts.google.com/o/oauth2/token 
    response: 
     status: 
      http_version: '1.1' 
      code: 200 
      message: OK 
     body: access_token=... 
- 
    request: 
     method: GET 
     url: https://www.googleapis.com/plus/v1/people/me 
    response: 
     status: 
      http_version: '1.1' 
      code: 200 
      message: OK 
     body: '{"emails":[{"value":"[email protected]"}],"id":"123","displayName":"John Doe","image":{"url":"https://googleusercontent.com/photo.jpg"}}' 

注意。あなたはphp-vcr/phpunit-testlistener-vcrが必要であり、あなたがあなたのphpunit.xmlに次の行を持っていることを確認してください:

<listeners> 
    <listener class="PHPUnit_Util_Log_VCR" file="vendor/php-vcr/phpunit-testlistener-vcr/PHPUnit/Util/Log/VCR.php"/> 
</listeners> 

もテストを実行する際に、設定されていない$_SERVER['HTTP_HOST']との問題がありました。私はここでconfig/services.phpファイル、つまりリダイレクトURLについて話しています。

<?php 

$app = include dirname(__FILE__) . '/app.php'; 

return [ 
    ... 
    'facebook' => [ 
     ... 
     'redirect' => (isset($_SERVER['HTTP_HOST']) ? 'http://' . $_SERVER['HTTP_HOST'] : $app['url']) . '/auth/facebook/callback', 
    ], 
]; 

特に美しくはないが、私はより良い方法を見つけることができなかった:私はそうのようにそれを処理していました。私はそこにconfig('app.url')を使用しようとしていましたが、設定ファイルでは動作しません。あなたは、このメソッドを削除するテストを実行し、どのようなビデオデッキ記録と備品の要求部を更新することによりsetUpBeforeClass一部を取り除くことができ

UPD。実際には、すべてがvcrmitmproxy)だけで行われるかもしれません。

+0

もしあれば、これはphp-vcrを使って本当に面白いアイデアです。 –

関連する問題