Search code examples
phpunit-testingsymfonyfunctional-testing

Symfony 4.2 unit testing wont works


I am doing unit testing / functional testing, but my code gives me an error. Kindly have a look on my code and suggest a solution.

Codes On Controller

    <?php

namespace App\Controller;


use App\Entity\Organization;
use App\Entity\User;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Psr\Log\LoggerInterface;
use Swift_Mailer;
use Swift_Message;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class RegisterController extends AbstractController
{

    protected $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    /**
     * Validate the data
     * Encodes the password
     * Creates new organization if evaplyId does not exists
     * Create user and send verification email.
     * return status
     *
     * @param Request $request
     * @param UserPasswordEncoderInterface $userPasswordEncoder
     * @param ValidatorInterface $validator
     * @param Swift_Mailer $mailer
     * @return Response
     */
    public function register(Request $request, UserPasswordEncoderInterface $userPasswordEncoder, ValidatorInterface $validator, Swift_Mailer $mailer)
    {
        try {
            $form = $request->getContent();
            $form = json_decode($form);
            $entityManager = $this->getDoctrine()->getManager(); //doctrine manager for entity managing
            $user = new User();
            $user->setEmail($form->email);
            if (!$this->checkEmail($form->email)) {
                return new JsonResponse(['status' => false, 'message' => 'Email already exists']);
            }
            $user->setFirstName($form->first_name);
            $user->setLastName($form->last_name);
            $user->setPassword($form->plain_password);
            if (!$form->evaply_id) {
                if(!$form->organization_name)
                    return new JsonResponse(['status' => false, 'message' => 'Missing field Organization']);
                $organization = new Organization();
                $organization->setName($form->organization_name);
                $startGuideStatus['status'] = false;
                $startGuideStatus['add_company'] = false;
                $startGuideStatus['first_connection'] = false;
                $startGuideStatus['first_scorecard'] = false;
                $startGuideStatus['first_order'] = false;
                $organization->setStartGuideStatus(($startGuideStatus));
                $organization->setCustOrSupplier($form->cust_or_supplier);
                $evaply_id = $this->generateEvaplyId($form->organization_name);
                $organization->setEvaplyId($evaply_id);
                $entityManager->persist($organization);
                $entityManager->flush();
            } else {
                $organization = $this->getDoctrine()->getRepository(Organization::class)->findOneBy(array('evaplyId' => $form->evaply_id));
                if (!$organization) {
                    return new JsonResponse(['status' => false, 'message' => 'Invalid Evaply ID']);
                }
            }
            $user->setOrganization($organization);
            $user->setUuid($this->generateUUID());
            $user->setRoles(['Admin']);
            $error = $validator->validate($user);
            if (count($error) > 0) {
                return new JsonResponse(['status' => false, 'message' => 'Validation error']);
            }
            if ($form->plain_password != $form->confirm_password) {
                return new JsonResponse(['status' => false, 'message' => 'Password miss match']);
            }
            $user->setPassword(
                $userPasswordEncoder->encodePassword(
                    $user,
                    $form->plain_password
                )
            );
            $token = $this->generateVerificationToken($user);
            $this->logger->info($token);
            $verificationUrl = $this->getParameter('app_url') . "account/verify/" . $token;
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($user);
            $entityManager->flush();
            $this->sendUserRegisteredMail($user, $verificationUrl, $mailer);

            return new JsonResponse(['status' => true, 'message' => "Successfully registered"]);
        } catch (\Exception $e) {
            $this->logger->error($e->getMessage());
            return new Response($e->getMessage());
        }
    }

    /**
     * Check email duplication in database
     *
     * @param $email
     * @return bool
     */
    public function checkEmail($email)
    {
        $user = $this->getDoctrine()->getRepository(User::class)->findOneBy(array('email' => $email));
        if ($user)
            return false;
        else
            return true;
    }

    /**
     * Generate a unique id using organization name and timestamp
     *
     * @param $orgName
     * @return string
     */
    public function generateEvaplyId($orgName)
    {
        $org = strtoupper(substr($orgName, 0, 3));
        $dateTime = time();
        $evaply_id = $org . $dateTime;
        return $evaply_id;
    }

    /**
     * Generate unique uuid for user
     * Recursive function
     *
     * @return int
     */
    public function generateUUID()
    {
        $uuid = rand(1000000000, 9999999999);
        $user = $this->getDoctrine()->getRepository(User::class)->findOneBy(array('uuid' => $uuid));
        if ($user) {
            return $this->generateUUID();
        } else {
            return $uuid;
        }
    }

    /**
     * Send email to user after a successfull registartion.
     *
     * @param User $user
     * @param Swift_Mailer $mailer
     * @return int
     */
    public function sendUserRegisteredMail(User $user, $verificationUrl, Swift_Mailer $mailer)
    {
        $message = (new Swift_Message("Successfully Registered"))
            ->setFrom('[email protected]')
            ->setTo($user->getEmail())
            ->setBody(
                $this->renderView(
                    'emails/registration.html.twig',
                    array('firstName' => $user->getFirstName(), 'lastName' => $user->getLastName(), 'verificationUrl' => $verificationUrl)
                ),
                'text/html'
            );
        return $mailer->send($message);
    }

    /**
     * Generates a verification token using aes-128-gcm encryption
     * encrypts email and uuid
     * encode ciphertext with base64 encoder
     *
     * @param User $user
     * @return string
     */
    public function generateVerificationToken(User $user)
    {
        $data = array();
        $data['email'] = $user->getEmail();
        $data['uuid'] = $user->getUuid();
        $plaintext = json_encode($data);
        $cipher = $this->getParameter('cipher');
        if (in_array($cipher, openssl_get_cipher_methods())) {

            $this->logger->info("inside cipher");
            //$ivlen = openssl_cipher_iv_length($cipher);
            $iv = $this->getParameter('secretIV');
            $key = $this->getParameter('cipher_key');
            //$tag = $this->getParameter('tagg');
            $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options = 0, $iv);
            $original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options = 0, $iv);
            return $token = base64_encode($ciphertext);
        }
    }
}

Codes On Tests/Controller Folder

   <?php
/**
 * Created by PhpStorm.
 * User: xavier-phases
 * Date: 22/1/19
 * Time: 5:09 PM
 */

namespace App\Tests\Controller;
use App\Controller\RegisterController;
use PHPUnit\Framework\TestCase;

class EvaplyTest extends TestCase
{

    public function testGenerate_evaply_clid(LoggerInterface $logger)
    {
        $id= new RegisterController();
        $org_name=$id->generateEvaplyId('Tset');
        $org = strtoupper(substr($org_name, 0, 3));
        $dateTime = time();
        $evaply_id = $org . $dateTime;
        return $evaply_id;
    }
}`

I am calling the generateEvaplyId() method from the register controller. I have installed all test packages. It gives me the following error:

"ArgumentCountError: Too few arguments to function App\Tests\Controller\EvaplyTest::testGenerate_evaply_clid(), 0 passed and exactly 1 expected".  KIndly have a look and suggest me a solution.

Solution

  • <?php
    
    namespace App\Tests\Controller;
    use App\Controller\RegisterController;
    use PHPUnit\Framework\TestCase;
    use PHPUnit\Framework\MockObject\MockObject;
    use Psr\Log\LoggerInterface;
    
    class EvaplyTest extends TestCase
    {
        /** @var LoggerInterface|MockObject */
        protected $logger;
        /** @var RegisterController **/
        protected $controller;
    
        /**
         * {@inheritdoc}
         */
        protected function setUp()
        {
            $this->logger = $this->createMock(LoggerInterface::class);
    
            $this->controller = new RegisterController(
                $this->logger,
            );
    
            parent::setUp();
        }
    
        public function testGenerate_evaply_clid()
        {
            $result = $this->controller->generateEvaplyId('Test');
            $this->assertEquals( 'TEST1548303737',$result);
    
    
        }
    }
    

    Here is how it should be. Initiate controller instance and all it's dependencies in setUp method, then, in all the tests you can reference them. By default, PHPUnit does not expect any dependencies for tests suite, what you tried to do is called data provider (check for data providers docs), it does require additional annotation and used for completely different purpose.

    And for the last, I do NOT recommend you to store any part of logic in controllers. Move everything to service layer. Controllers are only to catch request, pass it to manager and return response.