Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Bcrypt's avatar

Testing Multi-tenant.

Hi, I'm trying to create a database and migrate that new DB for a tenant but it keeps migrating to landlord. I swapped the database connection from landlord to tenant but the test is failing due to not finding the users table in the landlord DB.

I believe the Artisan command is running for the landlord and not the tenant.

I'm using Spatie's Laravel Multi-tenancy package and it is a new Laravel 9 app.

I thank you all for your help.

class RegistrationTest extends TestCase
{
        use DatabaseMigrations;
//        use RefreshDatabase;
//    use DatabaseTransactions;

    protected ?Tenant $tenant = null;

    protected function setUp () : void
    {
        parent::setUp();
        $this->artisan('migrate --path=database/migrations/landlord --database=landlord');
    }

    /**
     * @test
     * @throws \Throwable
     */
    public function guest_can_register()
    {
        $newUser = $this->make(User::class);
        $newUser = array_merge($newUser->toArray(), ['password' => 'password']);

        $newTenantData = $this->make(Tenant::class, ['database' => null]);
        $newTenant = [
            'tenant' => [
                'name' => $newTenantData->name,
                'domain' => $newTenantData->domain,
            ]
        ];

        $response = $this->postJson(
            route('register'),
            array_merge($newTenant, $newUser)
        );

        $tenant = Tenant::first();
        $this->setTenant($tenant);

        $this->assertDatabaseHas(
            'tenants',
            [
                'name' => $newTenant['tenant']['name'],
                'domain' => $newTenant['tenant']['domain'],
                'database' => $this->tenant->database
            ],
            'landlord'
        );

        $this->assertDatabaseHas(
            'users',
            Arr::except($newUser, 'password'),
            'tenant'
        );
    }

    public function setTenant($tenant)
    {
        $this->tenant = $tenant;
    }
}
class RegisterController extends Controller
{
    public function __invoke (Request $request)
    {
        $tenant = Tenant::create($request->get('tenant'));

        $user = User::create($request->except('tenant'));
        $user->tenants()->attach($tenant);

        return response()->json([
            'data' => $user,
        ], 201);
    }
}
class Tenant extends BaseTenant
{
    use HasFactory;

    protected $connection = 'landlord';
    protected $fillable = ['name', 'domain', 'database'];

    protected static function boot ()
    {
        parent::boot();
        static::created(function (Tenant $tenant) {
            $tenant->update(['database' => "arasek_{$tenant->id}_db"]);;
            $tenant->generateAccount();
        });
    }

    public function generateAccount(): void
    {
        $this->forgetCurrent();
        config(["multitenancy.tenant_database_connection_name" => 'tenant']);
        config(["database.connections.tenant.database" => $this->database]);

        DB::purge('landlord');
        DB::reconnect('tenant');
        $this->makeCurrent();
        try {
            DB::beginTransaction();
            DB::statement('CREATE DATABASE IF NOT EXISTS ' . $this->database);
            Artisan::call('tenants:artisan "migrate" --tenant=' . $this->id);
            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();

            dd($e->getMessage());
        }
    }
}

Error: Unknown database 'arasek_1_db' (SQL: select count(*) as aggregate from users where ...

So the DB is being created but when migrating the main DB is the one that gets the users table so by the time that this happens it fails:

$this->assertDatabaseHas(
            'users',
            Arr::except($newUser, 'password'),
            'tenant'
        );
0 likes
2 replies
Bcrypt's avatar

@Tray2 Thank you Tray, I'll take a look at it, I'm concerned about clients requesting isolated DB due to the nature of the app, but maybe you're right.

Please or to participate in this conversation.