Dahab
Dahab

Reputation: 514

Stripe payment functional test in a correct way

I am new to functional test, i am trying to implement that on the next function:

This is my controller how it looks

/**
 * @description prepare recurring stripe payment via Checkout Form
 * @author Mohamed Ragab Dahab <[email protected]>
 * @access public
 *
 * @param \Symfony\Component\HttpFoundation\Request $request 
 *
 * @Extra\Route(
 *   "/prepare_checkout/{payum_token}/{ownerType}",
 *   name="itjari_stripe_prepare_checkout"
 * )
 */
public function prepareCheckoutAction(Request $request, $ownerType) {
    $paymentName = 'stripe_checkout';
    $token = $this->get('payum.security.http_request_verifier')->verify($request);
    $payment = $this->getPayum()->getPayment($token->getPaymentName());
    $agreementStatus = new GetHumanStatus($token);
    $payment->execute($agreementStatus);

    $agreement = $agreementStatus->getFirstModel();
    $agreementDetails = $agreement->getDetails();
    // get agreement details
    $storage = $this->getPayum()->getStorage('ITJari\PaymentBundle\Entity\RecurringPaymentDetails');
    $details = $storage->create();
    $details["amount"] = $agreementDetails['amount'];
    $details["currency"] = $agreementDetails['currency'];
    $details["description"] = $agreementDetails['description'];
    $details["formData"] = $agreementDetails['formData'];
    $details["planName"] = $agreementDetails['planName'];
    // check if customer submitted the payment form and stripeToken got generated 
    if ($request->isMethod('POST') && $request->request->get('stripeToken')) {
        // set stripe api key required for [stripe-php lib] requests
        \Stripe::setApiKey($this->container->getParameter('stripe.secret_key'));
        // create a new customer and assign a plan to him using [stripe-php lib] 
        $customer = \Stripe_Customer::create([
                    'description' => $details['formData'][/* working for all owners */SubscriptionStudentInputs::GuardianFirstNameFieldName] . ' ' . $details['formData'][/* working for all owners */SubscriptionStudentInputs::GuardianLastNameFieldName],
                    'source' => $request->request->get('stripeToken'),
                    'plan' => $details['planName'],
        ]);
        // assign customer ID to payment charge method
        $details["customer"] = $customer->id;
        // charge and presist the customer and the payment
        $storage->update($details);

        $captureToken = $this->getTokenFactory()->createToken(
                $paymentName, $details, 'itjari_subscription_create_stripe_recurring_payment', ['ownerType' => $ownerType, 'agreementId' => $agreement->getId()]
        );

        return $this->redirect($captureToken->getTargetUrl());
    }
    // Render Checkout Form
    return $this->render("ITJariStripeBundle:PurchaseExamples:prepareCheckout.html.twig", [
                'publishable_key' => $this->container->getParameter('stripe.publishable_key'),
                'model' => $details,
                'paymentName' => $paymentName
                    ]
    );
}

Here is my functional test function: This is my controller how it looks

public function testPrepareCheckoutAction() {
    // owner types
    $ownerType = $this->Faker->randomElement(['teacher', 'student']);

    //Payum Token
    $payumToken = '';

    // params
    $params = array('payum_token' => $payumToken, 'ownerType' => $ownerType);

    // Route to tested action
    $crawler = $this->client->request(RequestMethods::GET, $this->router->generate('itjari_stripe_prepare_checkout', $params));

    // shorten
    $crawlerResponse = $this->client->getResponse();

    // Assert Page is loaded ok
    $this->assertEquals(200, $crawlerResponse->getStatusCode());

    $token = $this->container->get('payum.security.http_request_verifier')->verify();

    $payment = $this->container->get('payum')->getPayment($token->getPaymentName());

    //assert
    $this->assertInternalType('array', $payment);

    $agreementStatus = new \Payum\Core\Request\GetHumanStatus($token);
    $payment->execute($agreementStatus);
    $agreementDetails = $agreementStatus->getFirstModel()->getDetails();

    //assert
    $this->assertInternalType('array', $agreementDetails);
    //assert
    $this->assertArrayHasKey(array('amount', 'currency', 'description', 'formData', 'planName'), $agreementDetails);

    \Stripe::setApiKey($this->container->getParameter('stripe.secret_key'));
    $customer = \Stripe_Customer::create([
                'description' => $agreementDetails['formData'][/* working for all owners */\ITJari\StudentBundle\Services\SubscriptionStudentInputs::GuardianFirstNameFieldName] . ' ' . $agreementDetails['formData'][/* working for all owners */\ITJari\StudentBundle\Services\SubscriptionStudentInputs::GuardianLastNameFieldName],
                'source' => $this->request->get('stripeToken'),
                'plan' => $agreementDetails['planName'],
    ]);
    //assert
    $this->assertInstanceOf('\Stripe_Customer', $customer);
}

my question here i am doing the functional test in the correct way?

Upvotes: 0

Views: 890

Answers (1)

Aleksander Wons
Aleksander Wons

Reputation: 3967

  1. Your controller is way to big. You should move the entire payment into separate classes and then unit-test those classes without actually calling the payment provider. You can also use service in the controller to handle the payment.

which brings as to:

  1. To test your controller you can simply mock the service and return various values that are expected to test if all situations are handeled correctly.

or

  1. If your payment provider gives you an option to work in a sandbox, create a sandboxed version of the service and then you don't even need to mock it. Just define a different service in test environment.

Upvotes: 1

Related Questions