2017-01-24 19 views
0

私はCartCookieクラスをインスタンス化してショッピングカートを保存する独自のクッキーを生成するサービスプロバイダを持っています。これはシングルトンクラスであり、サービスコンテナに注入されます。 CartCookieクラスでユニットテスト中にサービスプロバイダでLaravel Cookieが利用できない

CartCookieServiceProvider.php

public function boot(Request $request) 
    { 
     $this->app->singleton(CartCookie::class, function ($app) use ($request) { 
      return new CartCookie($request); 
     }); 
    } 

CartCookie.php

use App\Cart; 
use Illuminate\Http\Request; 

class CartCookie 
{ 
    private $id; 
    private $request; 

    function __construct(Request $request) 
    { 
     $this->request = $request; 

     if ($request->cookie('cart_id')) { 
      $this->id = $request->cookie('cart_id'); 
     } else { 
      $this->id = $this->generateUniqueCartId(); 
     } 
    } 

    public function id() 
    { 
     return $this->id; 
    } 

    private function generateUniqueCartId() 
    { 
     do { 
      $id = md5(time() . 'cart' . rand(100000000000000, 9999999999999999)); 
     } while (Cart::find($id)); 

     return $id; 
    } 
} 

私はcart_idクッキーの存在を確認。アプリケーションを使用すると完全に正常に動作します!

私の問題は、ユニットテスト中にcart_idのクッキーが空であることですが、Requestがサービスプロバイダーから来た場合にのみ発生します。たとえば、ライフサイクルの後でコントローラからRequestを取得すると、そのクッキーが存在します。ここで

はテストの例です:

/** @test */ 
    public function get__store_checkout__checkout_displays_database_cart_correctly() 
    { 
     $cart = $this->createDatabaseCart(); 

     $cookie = ['cart_id' => Crypt::encrypt($this->cartCookie)]; 

     $response = $this->call('get', route('root.store.checkout'), [ 
      'seller_id' => $cart->seller->id, 
     ], $cookie); 

     $cart->seller->items()->each(function ($item) use ($response) { 
      $this->assertContains($beat->item, $response->getContent()); 
     }); 
    } 

私は、サービスプロバイダやカート機能を処理するコントローラの両方に要求クッキーをdd()ときに私は存在を伝えることができます。何らかの理由で、単体テストの間だけ、リクエストにまだサービスプロバイダにクッキーが含まれていません。

希望はこれが理にかなっています。ここから

+0

これは理にかなっていますか? –

+0

@DoniiHoho私はそれについては分かりません。 '$ this-> call()'はまったく新しいリクエストを開始しています。 – Wasim

+0

新しい要求を作成して、同じスクリプト実行内のルートに渡します。これは、シングルトンとしてマークしているためです。ここに問題があります。 –

答えて

2

link

してみてください。サービスプロバイダが最初にロードされた後、ルートへのユニット・テスト・コールが実行されるため

/** @test */ 
public function get__store_checkout__checkout_displays_database_cart_correctly() 
{ 
    $cart = $this->createDatabaseCart(); 

    $cookie = ['cart_id' => Crypt::encrypt($this->cartCookie)]; 

    //@TODO you must get the current request 
    //@TODO you must set $cookie to $request 
    //Or simply find a way to create the CartCookie you need using the $cookie from above 
    $cartCookie = new CartCookie($request); 

    //hopefully will swap the CartCookie::class instance 
    app()->instance(CartCookie::class, $cartCookie); 

    //Now that you have the CartCookie 
    $response = $this->call('get', route('root.store.checkout'), [ 
     'seller_id' => $cart->seller->id, 
    ], $cookie); 

    $cart->seller->items()->each(function ($item) use ($response) { 
     $this->assertContains($beat->item, $response->getContent()); 
    }); 
} 
+0

今すぐ取得できます。私は印象の下にあった ' - > call()'はAjaxの要求と同じように、毎回アプリケーションをインスタンス化するようになっていましたが、今は別の方法で見ています。私はあなたのサンプルのバリエーションを使ってテストを修正しました。 '$ cartCookie = app(CartCookie :: class); $ cartCookie-> setId($ this-> cartCookie); app() - > instance(CartCookie :: class、$ cartCookie); '理想的ではありませんが、テストはあなたの助けになり、何か新しいことを教えてくれます:) – Wasim

+0

乾杯! –

関連する問題