4

Looking deeper into this, I'm not sure it's even possible, which is a shame because I'm trying to learn TDD.

I would like to test my model with Billable being created and subscribed to a plan.

/** @test */
public function an_account_can_subscribe_to_a_plan() {
    $account = factory("App\Account")->create();

    Stripe::setApiKey('key');
    $paymentMethod = PaymentMethod::create([
        'type' => 'card',
        'card' => [
            'number' => '4242424242424242',
            'exp_month' => '2',
            'exp_year' => '2021',
            'cvc' => '314'
        ]
    ]);

    $subscription = $account->newSubscription('default', 'starter')->create($paymentMethod);
    $this->assertTrue( $subscription->valid() );  
}

The Laravel Cashier docs show how to send a token via Stripe.js, but that doesn't work for Unit Testing.

I've tried to include the Stripe library directly and create a PaymentMethod object, but this also requires me set an API key manually. Now the error I'm getting is that I have to verify my phone number to send raw credit card numbers to the stripe API.

I'm hoping there's a better way. How can I use Laravel Cashier in a TDD way and mock up fake subscriptions with fake payment methods?

Ramin eghbalian
  • 2,348
  • 1
  • 16
  • 36
good_afternoon
  • 1,529
  • 1
  • 12
  • 41

2 Answers2

8

Stripe provides not only test card numbers, but tokens and payment method's.

https://stripe.com/docs/testing#cards

Click the PaymentMethods tab. The value (for example pm_card_visa) can be used directly on the server-side in your tests without the need of front-end payment-intent implementation.

This is an example of a feature test I have:

    /**
     * @test
     */
    public function a_user_can_subscribe_to_a_paid_plan()
    {

        $this->actingAs($this->user);
        $this->setUpBilling();

        $enterprise = Plan::where('name', 'Enterprise')->first()->stripe_plan_id;

        $response = $this->post(route('paywall.payment'), [
            'payment_method' => 'pm_card_visa',
            'stripe_plan_id' => $enterprise
        ])
        ->assertSessionDoesntHaveErrors()
        ->assertRedirect();

    }

Your tests may vary, but you can make a normal request to your billing controller with these test payment methods and it goes through just as it would if you do it on the front-end.

good_afternoon
  • 1,529
  • 1
  • 12
  • 41
0

You may want to use stripe-mock for mocking during tests. If that doesn't fit your needs, mocking the objects directly may be a better option.

taintedzodiac
  • 2,658
  • 1
  • 18
  • 16
  • Thank you, I'll have to look into mocking. Seems strange to fake data like that when it comes to testing. Because now you can only be sure your mock data works, but you're not 100% certain real-world data works – good_afternoon Feb 25 '20 at 17:01