laravel 9 unit testing tutorial with example 2022

    By: Thad Mertz
    2 years ago

    In this guide we are going to create a small app which will display some structured data. and then we will step by step write the unit tests. We will create separate database for testing and also use factory for generating data in our tests.


    Important Links


    Data table: https://datatables.net/examples/styling/

    Laravel Assertions: https://laravel.com/docs/9.x/http-tests#available-assertions

    Faker: https://fakerphp.github.io/


    Important Commands

    npm install
    npm install -g npm@8.5.3
    npm install resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
    npm run dev
    
    
    composer require laravel/legacy-factories
    php artisan make:Test EmployeeTest --unit
    


    Let's start

    So we have a Controller function and code looks like this

    // Dashboard page.
        public function home()
        {
            try
            {
                $data = [];
                
                if(auth()->check())
                {
                    $employees =  Employee::all();
    
    
                    if(empty($employees->toArray()))
                    {
                        return [];
                    }
    
    
                    // Employees where salary is less than 60k. Type A
    
    
                    $employeeTypeA = (new EmployeeService)->getEmployeeTypeA($employees);
    
    
                    // Employees where salary is more than 60k and less than 100k. Type B
    
    
                    $employeeTypeB = (new EmployeeService)->getEmployeeTypeB($employees);
    
    
                    // Employees where salary is more than  100k. Type C
    
    
                    $employeeTypeC = (new EmployeeService)->getEmployeeTypeC($employees);
    
    
                    $data = [
                        'typeA' => $employeeTypeA,
                        'typeB' => $employeeTypeB,
                        'typeC' => $employeeTypeC,
                    ];
                   
                    return view('home')->with('data', $data);
    
                }
                
                return $data;
               
            }
            catch(Exception $e)
            {
                echo $e->getMessage();
            }
    
    
            return view('home');
        }
    

    Here we need to see how many tests cases are there so for example

    Testcase 1 is -> If user not logged in we should get empty array.

    Testcase 2 is -> If user logged in and employee data is not present again we get empty array.

    Testcase 3 is -> If user logged in and employee data present then we should return dashboard view with data.

    We are also going to check each function in service for getting data with our tests.

    Here is our tests

        /**
         * A basic unit test example.
         * 
         * @return void
         */
        public function test_if_user_not_logged_in()
        {
            $returnedValues = (new EmployeesController)->home();
            $this->assertEmpty($returnedValues);
           
            //$this->assertEquals([], $returnedValues);
        }
    

    For checking if employee data is not empty

        /**
         * @test
         */
        public function check_if_data_displayed_correctly_employee_dashboard()
        {
            // Create a user.
            $user = User::factory()->create([
                'password' => Hash::make('12345678'),
            ]);
    
    
            // Login the same user.
            $response = $this->post('login',[
                'email' => $user->email,
                'password' => '12345678',
            ]);
    
    
             //If loggedin check.
             $response->assertRedirect('/home');
    
    
    
             $employees =  Employee::factory(20)->create([
                'joining_date' => now()->toDateString(),
            ]);
    
    
            $employeeTypeAData = (new EmployeeService)->getEmployeeTypeA($employees);
            $employeeTypeBData = (new EmployeeService)->getEmployeeTypeB($employees);
            $employeeTypeCData = (new EmployeeService)->getEmployeeTypeC($employees);
    
    
            $data = [
                'typeA' => $employeeTypeAData,
                'typeB' => $employeeTypeBData,
                'typeC' => $employeeTypeCData,
            ];
    
    
            $employeeTypeData = [];
    
    
            // Get One emplyee from each type.
    
    
            foreach($employeeTypeAData as $employeeA)
            {
                $employeeTypeData['type_a'] = $employeeA['employee_name'];
            }
    
    
            foreach($employeeTypeBData as $employeeB)
            {
                $employeeTypeData['type_b'] = $employeeB['employee_name'];
            }
    
    
            foreach($employeeTypeCData as $employeeC)
            {
                $employeeTypeData['type_c'] = $employeeC['employee_name'];
            }
    
    
            // Get data from dashboard.
    
    
            $response = $this->get(route('home'));
    
    
            $this->assertTrue(collect($response['data']['typeA'])->contains('employee_name', $employeeTypeData['type_a']));
            $this->assertTrue(collect($response['data']['typeB'])->contains('employee_name', $employeeTypeData['type_b']));
            $this->assertTrue(collect($response['data']['typeC'])->contains('employee_name', $employeeTypeData['type_c']));
        }
    


    Also tests for our service file where we are modifying data for example here

        /**
         * Get Employee Type A data where salary less than 60k.
         */
        public function getEmployeeTypeA($employees)
        {
            $data = [];
    
    
            // get employee where salary is less than 60k.
    
    
           foreach($employees as $employee)
           {
                 if((int) $employee->salary < 60000)
                 {
                    $data['id']             = $employee->id;
                    $data['employee_id']    = $employee->employee_id;
                    $data['employee_name']  = $employee->employee_name;
                    $data['age']            = $employee->age;
                    $data['joined']         = $employee->joining_date;
                    $data['salary']         = $employee->salary;
                    $data['bonus']          = $employee->bonus;
                    $data['med_claims']     = $employee->employee_medical_claims;
                    $data['allowences']     = $employee->allowences;
                    $data['leave_payments'] = $employee->leave_payments;
    
    
                    $data['totalExpense']   = $employee->salary +
                                              $employee->bonus +
                                              $employee->employee_medical_claims +
                                              $employee->allowences +
                                              $employee->leave_payments;
    
    
                    $this->getEmployeeTypeA[] = $data;
                }
               
           }
    
    
           return $this->getEmployeeTypeA;
        }
    

    Here is the test for it

    /**
         * Checks for type a data is returning from service function.
         */
        public function test_get_employee_type_a_not_empty()
        {
            $employees = Employee::factory(200)->create([
                'joining_date' => now()->toDateString(),
            ]);
    
    
            $response = (new EmployeeService)->getEmployeeTypeA($employees);
    
    
            $this->assertNotEmpty($response);
        }
    

    Check video guide for explanation.

    improve this guide leave your thoughts...