jeudi 30 juillet 2015

Mocking class parameter that returns a mock in Laravel 5.1

I am new to unit testing and trying to test a controller method in Laravel 5.1 and Mockery.

I am trying to test a registerEmail method I wrote, below

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Response;
use Mailchimp;
use Validator;

/**
 * Class ApiController
 * @package App\Http\Controllers
 */
class ApiController extends Controller
{

    protected $mailchimpListId = null;
    protected $mailchimp = null;

    public function __construct(Mailchimp $mailchimp)
    {
        $this->mailchimp = $mailchimp;
        $this->mailchimpListId = env('MAILCHIMP_LIST_ID');
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function registerEmail(Request $request)
    {

        $this->validate($request, [
            'email' => 'required|email',
        ]);

        $email  = $request->get('email');

        try {
            $subscribed = $this->mailchimp->lists->subscribe($this->mailchimpListId, [ 'email' => $email ]);
            //var_dump($subscribed);
        } catch (\Mailchimp_List_AlreadySubscribed $e) {
            return Response::json([ 'mailchimpListAlreadySubscribed' => $e->getMessage() ], 422);
        } catch (\Mailchimp_Error $e) {
            return Response::json([ 'mailchimpError' => $e->getMessage() ], 422);
        }

        return Response::json([ 'success' => true ]);
    }
}

I am attempting to mock the Mailchimp object to work in this situation. So far, my test looks as follows:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class HomeRouteTest extends TestCase
{

    public function testMailchimpReturnsDuplicate() {
        $listMock = Mockery::mock('Mailchimp_Lists')
            ->shouldReceive('subscribe')
            ->once()
            ->andThrow(\Mailchimp_List_AlreadySubscribed::class);

        $mailchimp = Mockery::mock('Mailchimp')->lists = $listMock;

        $this->post('/api/register-email', ['email'=>'duplicate@email.com'])->assertJson(
            '{"mailchimpListAlreadySubscribed": "duplicate@email.com is already subscribed to the list."}'
        );
    }
}

I have phpUnit returning a failed test, 1) HomeRouteTest::testMailchimpReturnsDuplicate Mockery\Exception\InvalidCountException: Method subscribe() from Mockery_0_Mailchimp_Lists should be called exactly 1 times but called 0 times.

Also, if I assert the status code is 422, phpUnit reports it is receiving a status code 500.

It works fine when I test it manually, but I imagine I am overlooking something fairly easy, so your guidance is much appreciated. Thank you!

Aucun commentaire:

Enregistrer un commentaire