DEV Community

Cover image for Testing Applications In Laravel.
Jeffrey Kwade
Jeffrey Kwade

Posted on • Edited on

Testing Applications In Laravel.

## Exploring Uncommon Error Messages When Running Tests in Laravel

Hello developers,

Welcome to my first episode in the "Testing Applications in Laravel" series. In this series, I will discuss different topics related to testing Laravel applications. Today, I will be discussing some rare errors that you might encounter while running tests in Laravel.

When it comes to testing, encountering errors is inevitable. It can be frustrating, and it's common to feel like screaming at your computer. However, with a little knowledge and understanding, you can quickly fix these errors and make your tests pass.

Today we shall discuss Error: Test code or tested code did not (only) close its own output buffers.

The error message Error: Test code or tested code did not (only) close its own output buffers is a common issue in PHPUnit tests when output buffering is used. Output buffering is a feature in PHP that allows you to capture the output of a script and manipulate it before it is sent to the browser.

When PHPUnit tests are run, they capture any output from the test code and compare it with the expected output. If there is any output left in the buffer after the test is complete, it can cause this error.

A junior developer reached out to me seeking assistance with the 'Error: Test code or tested code did not (only) close its own output buffers' issue. She had tried several methods, but none seemed to work. It brought back memories from when I first encountered this error, and I remember how frustrating it was to solve. Unfortunately, most articles related to this error are outdated or not clearly explained, which can make it challenging for junior developers to understand and resolve the issue.

The issue with this error is that it can be difficult to diagnose because it doesn't always output a clear error message. In many cases, the console will generate a more specific error message that can help us pinpoint the root cause of the issue. This is why it's important to pay close attention to any error messages that are generated by your application and use them as a starting point for troubleshooting.

So, to solve this error, we need to retrieve the output buffer levels using ob_get_level(). This allows us to check whether there are any open output buffers that haven't been closed. We then retrieve the contents of the output buffer using ob_get_contents() and clear the buffer using ob_end_clean().

It's important to note that many solutions online advise using ob_start() at the beginning of the test and ob_end_clean() at the end. However, this doesn't always work for complex test cases.

Now, let's move on to the coding part and see how we can implement this solution.

<?php

namespace Tests\Unit\V1\Admin\Vehicle;

use App\Http\Livewire\Admin\Vehicle\Add;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
use Tests\TestCase;

class VehicleTest extends TestCase
{
    use RefreshDatabase, WithoutMiddleware;



    public function test_create_new_vehicle_entry_with_file_upload()
    {

        ob_start();
        Storage::fake('avatars');

        $user = User::factory()->create();
        $this->actingAs($user);
        Auth::login($user);

        $file = UploadedFile::fake()->image('avatar.jpg');

        Livewire::test(Add::class)
                ->set([
                    'name' => 'Toyota',
                    'reg_num' => 'GD-123-12',
                    'vin_num' => 'kajsy',
                    'status' => true,
                    'home_away' => true,
                    'image' => $file,
                    'transmission' => 'automatic',
                    'price' => '1000',
                    'fuel' => 'petrol',
                    'mileage' => 1000
                ])
                ->call('create')
                ->assertSet('image', $file->name)
                ->assertHasNoErrors(['name', 'reg_num']);
                 Storage::disk('avatars')->assertExists($file->hashName());
                $this->assertAuthenticatedAs($user);
                $this->assertTrue(Auth::check());
                $this->assertDatabaseHas('vehicles', [
                    'name' => 'Toyota',
                    'reg_num' => 'GD-123-12',
                    'vin_num' => 'kajsy',
                    'serviced' => null,
                    'status' => true,
                    'home_away' => true,
                    'transmission' => 'automatic',
                    'price' => 1000,
                    'fuel' => 'petrol',
                ]);
                ob_get_contents();
                ob_end_clean();
    }
}
Enter fullscreen mode Exit fullscreen mode

In the code block above, we are writing a test to add a new vehicle record to the database. Now I have intentionally added code blocks to specifically throw Error: Test code or tested code did not (only) close its own output buffers, which is `assertSet('image', $file).

Let's take a look a the console when we run this test despite including ob_start() and ob_end_clean().

`
There was 1 risky test:

1) Tests\Unit\V1\Admin\Vehicle\VehicleTest::test_create_new_vehicle_entry_with_file_upload
Test code or tested code did not (only) close its own output buffers

F:\projects\Laravel\live2\tests\Unit\V1\Admin\Vehicle\VehicleTest.php:21

FAILURES!
Tests: 1, Assertions: 1, Failures: 1, Risky: 1.
`

The error message still isn't clearly stated, now I'm going to refactor the code and run the test.

`
public function test_create_new_vehicle_entry_with_file_upload()
{

    while (ob_get_level() > 0) {
        ob_end_clean();
    }
    Storage::fake('avatars');

    $user = User::factory()->create();
    $this->actingAs($user);
    Auth::login($user);

    $file = UploadedFile::fake()->image('avatar.jpg');

    Livewire::test(Add::class)
            ->set([
                'name' => 'Toyota',
                'reg_num' => 'GD-123-12',
                'vin_num' => 'kajsy',
                'status' => true,
                'home_away' => true,
                'image' => $file,
                'transmission' => 'automatic',
                'price' => '1000',
                'fuel' => 'petrol',
                'mileage' => 1000
            ])
            ->call('create')
            ->assertSet('image', $file->name)
            ->assertHasNoErrors(['name', 'reg_num']);
            Storage::disk('avatars')->assertExists($file);
            $this->assertAuthenticatedAs($user);
            $this->assertTrue(Auth::check());
            $this->assertDatabaseHas('vehicles', [
                'name' => 'Toyota',
                'reg_num' => 'GD-123-12',
                'vin_num' => 'kajsy',
                'serviced' => null,
                'status' => true,
                'home_away' => true,
                'transmission' => 'automatic',
                'price' => 1000,
                'fuel' => 'petrol',
            ]);
            ob_get_contents();
            ob_end_clean();
}
Enter fullscreen mode Exit fullscreen mode

`

I have replaced ob_start() with ob_get_level() in a conditional statement that'll trigger ob_end_clean() when it surpasses 0. Let's take a look at the error message.

`
PS F:\projects\Laravel\live2> ./vendor/bin/phpunit --filter=VehicleTest
PHPUnit 10.0.11 by Sebastian Bergmann and contributors.

Runtime: PHP 8.2.0
Configuration: F:\projects\Laravel\live2\phpunit.xml

F 1 / 1 (100%)

Time: 00:01.956, Memory: 42.00 MB

There was 1 failure:

1) Tests\Unit\V1\Admin\Vehicle\VehicleTest::test_create_new_vehicle_entry_with_file_upload
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'avatar.jpg'
+'livewire-file:RxzKXRUzs3bLTN9IHbWBFtHgfTLRb4-metaYXZhdGFyLmpwZw==--size=695.jpg'

F:\projects\Laravel\live2\vendor\livewire\livewire\src\Testing\Concerns\MakesAssertions.php:22
F:\projects\Laravel\live2\tests\Unit\V1\Admin\Vehicle\VehicleTest.php:50
F:\projects\Laravel\live2\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestCase.php:173

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
`

Now we get a clear error message that will allow us to properly Debug our code.

Now that we have a clear understanding of how to handle the Error: Test code or tested code did not (only) close its own output buffers issue, we'll be diving deeper into the topic of debugging in our next episode. We'll cover some essential tools and techniques that every developer should have in their toolkit to troubleshoot issues quickly and effectively. Stay tuned!

Be sure to follow me on twitter, github, showwcase at @rebelnii and subscribe to my YouTube

Top comments (1)

Collapse
 
da7483 profile image
David Emmanuel

Make sure to follow dev community in all social network medias as described below to experience the knowledge of AI automation in Web3 and gain full knowdge to fight and secure your work, privacy, friends and family from cyber security theft