2017-01-24 67 views
0

我有一个服务提供商,它实例化了一个CartCookie类,该类生成一个用于保存购物车的独特cookie。这是一个单例类,它被注入到服务容器中。Laravel饼干在单元测试期间不在服务提供商处提供

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; 
    } 
} 

CartCookie类我查了cart_id cookie的存在。使用应用程序时工作得很好!

我的问题是,在单元测试期间,cart_id cookie为空,但仅当Request来自服务提供商时。例如,如果我在生命周期的后期从控制器获取Request,则存在Cookie。

下面是测试的一个例子:

/** @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()请求饼干在两个服务提供商和处理车功能的控制器。出于某种原因,只有在单元测试期间,请求中不包含服务提供者中的cookie。

希望这是有道理的。

+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($这个 - > cartCookie);应用程序() - >实例(CartCookie :: class,$ cartCookie);'不理想,但测试通过,所以感谢您的帮助,并教我新东西:) – Wasim

+0

干杯队友,很高兴它帮助! –