Testing Applications In Laravel.
Tags: laravel, testing, tutorial, webdev
Published: 2023-04-09 00:29:23

[](url)## 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();
    }
}
```
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();
    }

```

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]('https://twitter.com/kwade_jeffrey'), github, showwcase at @RebelNii and subscribe to my [YouTube](https://www.youtube.com/@RebelBase596?sub_confirmation=1)