NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

MediaLibrary::fake() swaps the manager for a recording fake and returns it:

use RoundlyConsulting\MediaLibrary\Facades\MediaLibrary;

$fake = MediaLibrary::fake();

$this->post('/profile/avatar', ['avatar' => UploadedFile::fake()->image('me.png')]);

$fake->assertAdded('avatar', to: $user);
$fake->assertNothingDeleted();
  • It writes nothing — no file on any disk, no row, no queued job, no event — so a test needs neither real disks nor Storage::fake().
  • It records every call, whether it came through the facade, an injected MediaLibraryManager, a for() handle, the InteractsWithMedia trait or a Media model method.
  • Mutations still return something realistic: adds, attaches and copies return an unsaved Media with a fresh uuid, owner, bucket, disk, visibility and the same safe file name a real add stores; moves re-point the media in memory.
  • Bucket acceptance rules (mime allowlist, size cap, image dimensions) still apply to adds and draft binds, and an unknown or expired draft token still throws. Reads run against the database as usual.

Assertions

Every argument is an optional filter; null matches anything:

$fake->assertAdded('avatar', to: $user);
$fake->assertAttached($logo, to: $user, bucket: 'avatar');
$fake->assertDraftBound($token, to: $user, bucket: 'avatar');
$fake->assertMoved($media, to: $otherUser, bucket: 'gallery', disk: 'cold');
$fake->assertVariantsMoved($media, disk: 'hot');
$fake->assertCopied($media, to: $otherUser, bucket: 'gallery');
$fake->assertReplaced($media);
$fake->assertDeleted($media);            // clear() records one delete per media
$fake->assertRegenerated($media, only: ['thumb'], force: true);
$fake->assertDraftsPruned();

// The negative counterparts
$fake->assertNothingAdded();
$fake->assertNothingAttached();
$fake->assertNothingBound();
$fake->assertNothingMoved();
$fake->assertNoVariantsMoved();
$fake->assertNothingCopied();
$fake->assertNothingReplaced();
$fake->assertNothingDeleted();
$fake->assertNothingRegenerated();
$fake->assertDraftsNotPruned();

End-to-end against a faked disk

When you want real files and generated variants, skip the fake and use Storage::fake() for the bucket's disks:

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use RoundlyConsulting\MediaLibrary\Facades\MediaLibrary;

it('stores an avatar and generates a thumbnail', function () {
    Storage::fake('cold');
    Storage::fake('hot');

    $user = User::factory()->create();
    MediaLibrary::for($user)
        ->add(UploadedFile::fake()->image('me.jpg', 600, 600))
        ->toBucket('avatar');

    $avatar = MediaLibrary::for($user)->first('avatar');

    expect($avatar->hasGeneratedVariant('thumb'))->toBeTrue();
    Storage::disk('cold')->assertExists($avatar->getPath());
});

Run your suite with the package's migration loaded (RefreshDatabase). Queued variants run synchronously under the sync queue in tests, so generated variants are assertable immediately.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.