Giter VIP home page Giter VIP logo

Comments (28)

ArtisanTinkerer avatar ArtisanTinkerer commented on June 30, 2024 1

I think using MySQL will be a last resort. I want to run in memory, so that my tests run quickly.

from laravel-multitenancy.

freekmurze avatar freekmurze commented on June 30, 2024 1

Closing this as this is not a problem for the package tests, and it's also not an issue in our projects. If you find a solution, feel free to post it below, might be helpful for others.

from laravel-multitenancy.

masterix21 avatar masterix21 commented on June 30, 2024 1

Using Tenant::first()->makeCurrent() and Tenant::current()->forget(), or if you like:

Tenant::first()->execute(function () {
// all your tenant-aware tests :)
});

from laravel-multitenancy.

adarmanto avatar adarmanto commented on June 30, 2024 1

I just want to share how to configure the unit tests in my environment using Laravel v9 (as I was a bit lost about):

How to configure the unit tests for spatie/laravel-multitenancy package

On your test you need to replace RefreshDatabase with TenantAware :

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\Tenant;
use Tests\Concerns\TenantAware;

class ExampleTest extends TestCase
{
    use TenantAware;

    public function testExample()
    {  
        $this->assertTrue(Tenant::checkCurrent());
    }
}

from laravel-multitenancy.

masterix21 avatar masterix21 commented on June 30, 2024

You can't switch a :memory: database

from laravel-multitenancy.

ArtisanTinkerer avatar ArtisanTinkerer commented on June 30, 2024

How do you do any automated testing then?

Somehow I need to configure two databases (landlord and one tenant) and be able to test against them.

from laravel-multitenancy.

masterix21 avatar masterix21 commented on June 30, 2024

Yes, sure: it's what we already done in our tests. You can use MySQL.

from laravel-multitenancy.

masterix21 avatar masterix21 commented on June 30, 2024

If you'll find a solution, keep us updated. Thanks

from laravel-multitenancy.

ArtisanTinkerer avatar ArtisanTinkerer commented on June 30, 2024

How to you TDD when using this package? Using MySQL instead of SQLite?

from laravel-multitenancy.

masterix21 avatar masterix21 commented on June 30, 2024

yes

from laravel-multitenancy.

freekmurze avatar freekmurze commented on June 30, 2024

Me too, I find that using MySQL is far more easier that SQLite. In SQLite certain functions (and json handling) doesn't exist or is a bit different than in MySQL.

from laravel-multitenancy.

masterix21 avatar masterix21 commented on June 30, 2024

IMHO it's better to test your application with the same database that you will use in the production environment: it will improve the test experience, and the feedback is more near to real.

from laravel-multitenancy.

ArtisanTinkerer avatar ArtisanTinkerer commented on June 30, 2024

OK, I'm going to give it a go.

I'd love to see your testing config (phpunit.xml, database.php) for running tests against landlords and tenants.

from laravel-multitenancy.

ArtisanTinkerer avatar ArtisanTinkerer commented on June 30, 2024

I have a tenant db and a landlord db set up for testing (MySQL). How do you switch in a test?

from laravel-multitenancy.

ArtisanTinkerer avatar ArtisanTinkerer commented on June 30, 2024

I am doing that in a test:

Tenant::first()->makeCurrent();

When I look a the connection, it is still connected to the landlord:

result = {Illuminate\Database\MySqlConnection} [18]
 resolvers = {array} [0]
 pdo = {Doctrine\DBAL\Driver\PDOConnection} [0]
 readPdo = null
 database = "landlord"

and \DB::select('SHOW TABLES')
Shows tables from the landlord.

Am I doing something silly?

phpunit

<server name="DB_CONNECTION" value="landlord"/>
 <server name="DB_DATABASE" value="landlord"/>

database.php

'landlord' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('LANDLORD_DB_HOST'),
            'port' => env('LANDLORD_DB_PORT'),
            'database' => env('LANDLORD_DB_DATABASE'),
            'username' => env('LANDLORD_DB_USERNAME'),
            'password' => env('LANDLORD_DB_PASSWORD'),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

        'tenant' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('TENANT_DB_HOST'),
            'port' => env('TENANT_DB_PORT'),
            'database' => env('TENANT_DB_DATABASE'),
            'username' => env('TENANT_DB_USERNAME'),
            'password' => env('TENANT_DB_PASSWORD'),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

.env

DB_CONNECTION=landlord
LANDLORD_DB_HOST=mysql
LANDLORD_DB_PORT=3306
LANDLORD_DB_DATABASE=landlord
LANDLORD_DB_USERNAME=default
LANDLORD_DB_PASSWORD=secret

TENANT_DB_HOST=mysql
TENANT_DB_PORT=3306
TENANT_DB_DATABASE=null
TENANT_DB_USERNAME=default
TENANT_DB_PASSWORD=secret

multitenancy.php

'tenant_finder' => Spatie\Multitenancy\TenantFinder\DomainTenantFinder::class,
'tenant_database_connection_name' => 'tenant',
'landlord_database_connection_name' => 'landlord',
'switch_tenant_tasks' => [
        // add tasks here
        Spatie\Multitenancy\Tasks\SwitchTenantDatabaseTask::class,
    ],

from laravel-multitenancy.

ArtisanTinkerer avatar ArtisanTinkerer commented on June 30, 2024

OK, I'm an idiot. I was it expecting it to swap the DB:connection() but it doesn't.
The package sets the configuration for the tenant db and the models then use the correct db (via the traits).
Neat!

from laravel-multitenancy.

jartaud avatar jartaud commented on June 30, 2024

@ArtisanTinkerer Actually MySQL is faster than SQlite:

  • Use DatabaseTransactions
  • Migrate your test DB php artisan migrate --database=mysql_testing

Pros
You can use any MySQL function like DATE_FORMAT, tmp.category_name->>"$.'.$lang.'" as fmt_category_name
You can make sure that your foreign key constraints will work in production

Cons
You have to migrate your test DB php artisan migrate --database=mysql_testing just like your local DB


I'm getting :

Time: 3.13 minutes, Memory: 596.00 MB
OK (1508 tests, 7787 assertions)

from a 4 years old HP running Ubuntu Budgie 18.04 with HDD

from laravel-multitenancy.

gssoftnepal avatar gssoftnepal commented on June 30, 2024

Hi, php artisan test runs fine, but when I try to run php artisan test -p it throws errors. Any suggestions?

from laravel-multitenancy.

masterix21 avatar masterix21 commented on June 30, 2024

@gssoftnepal what's the error?

from laravel-multitenancy.

gssoftnepal avatar gssoftnepal commented on June 30, 2024

I am using Laravel Sail with multiple databases, when I run php artisan test -p, I get this error Illuminate\Database\QueryException: SQLSTATE[42000]: Syntax error or access violation: 1044 Access denied for user 'sail'@'%' to database '_test_4' (SQL: drop database if exists _test_4)

from laravel-multitenancy.

jartaud avatar jartaud commented on June 30, 2024

@gssoftnepal

I am using Laravel Sail with multiple databases, when I run php artisan test -p, I get this error Illuminate\Database\QueryException: SQLSTATE[42000]: Syntax error or access violation: 1044 Access denied for user 'sail'@'%' to database '_test_4' (SQL: drop database if exists _test_4)

You need to run sail artisan test

from laravel-multitenancy.

gssoftnepal avatar gssoftnepal commented on June 30, 2024

At first I ran sail shell and then ran php artisan test. This runs fine. I also ran sail artisan test in my local terminal, it also runs fine, but when I run php artisan test -p or sail artisan test -p, all of my tests fail and I get this error: Illuminate\Database\QueryException: SQLSTATE[42000]: Syntax error or access violation: 1044 Access denied for user 'sail'@'%' to database '_test_4' (SQL: drop database if exists _test_4)

from laravel-multitenancy.

valh1996 avatar valh1996 commented on June 30, 2024

@adarmanto Thanks for sharing. But i'm getting this error running php artisan test:

  There is no active transaction

  at vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php:291
    287▕      */
    288▕     protected function performRollBack($toLevel)
    289▕     {
    290▕         if ($toLevel == 0) {
  ➜ 291▕             $this->getPdo()->rollBack();
    292▕         } elseif ($this->queryGrammar->supportsSavepoints()) {
    293▕             $this->getPdo()->exec(
    294▕                 $this->queryGrammar->compileSavepointRollBack('trans'.($toLevel + 1))
    295▕             );

      +2 vendor frames 
  3   tests/Concerns/TenantAware.php:106
      Illuminate\Database\Connection::rollBack()

Note: I have only one test exactly like yours above.

EDIT

I was creating the tenant table in the createDatabase method as follows:

Schema::createDatabase($this->getDatabaseName());

I upgraded using the DB facade and I no longer have a transaction problem (like your example):

\DB::connection($this->tenantDatabaseConnectionName())->statement("CREATE DATABASE {$this->getDatabaseName()}");

from laravel-multitenancy.

valh1996 avatar valh1996 commented on June 30, 2024

@adarmanto Just a small point, how do you deal with the fact that when you do php artisan test, it will create a tenant and its database, but the second time you run this command it will not work because the testing_tenant_db database already exists?

from laravel-multitenancy.

adarmanto avatar adarmanto commented on June 30, 2024

@valh1996 in your case, you can skip creating the tenant database on testing like so:

if (! app()->runningUnitTests()) {
    // Skip the tenant DB creation
}

Note: this is one of my reason to put the tenant DB creation into Queue so either I can mock it to skip it while testing and also test it as my example.

from laravel-multitenancy.

valh1996 avatar valh1996 commented on June 30, 2024

@adarmanto Thank you.

I ended up just adding IF NOT EXISTS when creating a new database:

DB::connection($this->tenantDatabaseConnectionName())->statement("CREATE DATABASE IF NOT EXISTS {$this->getDatabaseName()}");

Let me ask you another question, how do you deal with laravel built-in asserts like $this->assertAuthenticated();, it always uses the landlord connection. Any idea please?

from laravel-multitenancy.

adarmanto avatar adarmanto commented on June 30, 2024

@valh1996 I put the authentication tables (users, password_reset, etc) into the landlord database, but set the tenant connection as my default DB and there is no issue when running default-generated tests from Starter Kit (using Inertia in my case). Don't forget to use Spatie\Multitenancy\Models\Concerns\UsesLandlordConnection trait in any models that use landlord connection.

from laravel-multitenancy.

valh1996 avatar valh1996 commented on June 30, 2024

@adarmanto I see, I use landlord as default connection. I have authentication at the landlord level, then in each tenant. Thanks for you response.

from laravel-multitenancy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.