jeudi 30 mai 2019

PHPUnit mock a class method to return certain value after api call

I'm writing a test in Laravel 5.8 to check some database records get created and relationships exists etc, after an api call is made.

The api call runs a method on a class that makes its own api call to an external service that is needed in the real world but I don't care about it in the test.

I want to mock that class / method so it returns a certain value so that I can forget about it in the test.

Here is my test below, I have attempted to mock the PayPointAdapter class and specifically the makePayment method.

/** @test */
    public function client_can_make_a_payment()
    {
        $client = factory(Client::class)->create();
        $invoice = factory(Invoice::class)->create([
            'client_id' => $client->id
        ]);
        $card = factory(PaymentCard::class)->make([
            'client_id' => $client->id
        ]);

        $this->assertCount(0, $client->payments);
        $this->assertCount(0, $client->paymentCards);

        $mock = \Mockery::Mock(PayPointAdapter::class)
            ->allows(['makePayment' => ["status" => "success", "transid" => 123]]);

        $response = $this->json(
            'POST',
            '/api/payments',
            [
                'invoiceid'                 => $invoice->id,
                'amount'                    => $invoice->total(),
                'clientdetails-firstname'   => $client->first_name,
                'clientdetails-lastname'    => $client->last_name,
                'clientdetails-email'       => $client->email,
                'clientdetails-address1'    => $client->address_line_one,
                'clientdetails-address2'    => $client->address_line_two,
                'clientdetails-city'        => $client->city,
                'clientdetails-state'       => $client->state,
                'clientdetails-postcode'    => $client->postcode,
                'clientdetails-phonenumber' => '',

                'cardtype'     => $card->type,
                'cardnum'      => $card->number,
                'cardexp'      => $card->expiry,
                'cardstart'    => $card->start,
                'cardissuenum' => $card->issue,
                'cccvv'        => $card->ccv
            ]
        );

        $response->assertStatus(201);
        $client->refresh();
        $invoice->refresh();
        $this->assertCount(1, $client->paymemnts);
        $this->assertCount(1, $client->paymentCards);
        $this->assertDatabaseHas('payment_cards', $card->toArray());
        $this->assertTrue($invoice->isPaid());
    }

Here is the method in the controller that handles the api call

/**
     * Make a payment.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return bool
     */
    public function store(Request $request)
    {
        try {
            $payment = $this->payPointAdapter->makePayment($request->all());

            $card = PaymentCard::where('type', request('cardtype'))
                ->where('expiry', request('cardexp'))
                ->where('start', request('cardstart'))
                ->where('ccv', request('cccvv'))
                ->get()
                ->filter(function ($paymentCard) {
                    return $paymentCard->number == request('cardnum');
                });

            if (!$card) {
                $card = PaymentCard::create([
                    'number' => request('cardnum'),
                    'type'   => request('cardtype'),
                    'expiry' => request('cardexp'),
                    'start'  => request('cardstart'),
                    'issue'  => request('cardissuenum')
                ]);
            }

            Payment::create([
                'invoice_id'      => request('invoiceid'),
                'amount'          => request('amount'),
                'payment_method'  => request('payment_method'),
                'payment_card_id' => $card->id,
                'reference'       => $payment['transid']
            ]);

            return response($payment, 201);
        } catch (\Exception $ex) {
            return response($ex->getMessage(), 500);
        }
    }

So I simply want to ignore the call to method $this->payPointAdapter->makePayment($request->all()); and get the test to mock the response to that.

In my test the mock I created doesn't stop it running the method. Any ideas?

Aucun commentaire:

Enregistrer un commentaire