Skip to content

Switch tests to SQLite to remove the need for MySQL server #2616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions .github/workflows/build-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@ jobs:
php:
- '8.1'
- '8.2'
services:
mysql:
image: mysql:8.0
ports:
- 3307:3306
env:
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
MYSQL_DATABASE: 'unittest'
MYSQL_ROOT_PASSWORD:

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -77,8 +68,6 @@ jobs:
./vendor/bin/phpunit --coverage-clover coverage.xml
env:
MONGODB_URI: 'mongodb://127.0.0.1/?replicaSet=rs'
MYSQL_HOST: 0.0.0.0
MYSQL_PORT: 3307
- uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
3 changes: 1 addition & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ Before submitting a pull request:
## Run Tests

The full test suite requires PHP cli with mongodb extension, a running MongoDB server and a running MySQL server.
Tests requiring MySQL will be skipped if it is not running.
Duplicate the `phpunit.xml.dist` file to `phpunit.xml` and edit the environment variables to match your setup.

```bash
$ docker-compose up -d mongodb mysql
$ docker-compose up -d mongodb
$ docker-compose run tests
```

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ RUN apt-get update && \
apt-get install -y autoconf pkg-config libssl-dev git unzip libzip-dev zlib1g-dev && \
pecl install mongodb && docker-php-ext-enable mongodb && \
pecl install xdebug && docker-php-ext-enable xdebug && \
docker-php-ext-install -j$(nproc) pdo_mysql zip
docker-php-ext-install -j$(nproc) zip

COPY --from=composer:2.6.2 /usr/bin/composer /usr/local/bin/composer

Expand Down
13 changes: 0 additions & 13 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,9 @@ services:
working_dir: /code
environment:
MONGODB_URI: 'mongodb://mongodb/'
MYSQL_HOST: 'mysql'
depends_on:
mongodb:
condition: service_healthy
mysql:
condition: service_started

mysql:
container_name: mysql
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD:
MYSQL_DATABASE: unittest
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'

mongodb:
container_name: mongodb
Expand Down
2 changes: 1 addition & 1 deletion docs/eloquent-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ If you want this functionality to work both ways, your SQL-models will need to u

**This functionality only works for `hasOne`, `hasMany` and `belongsTo`.**

The MySQL model should use the `HybridRelations` trait:
The SQL model should use the `HybridRelations` trait:

```php
use MongoDB\Laravel\Eloquent\HybridRelations;
Expand Down
34 changes: 2 additions & 32 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,14 @@
>
<coverage/>
<testsuites>
<testsuite name="all">
<testsuite name="Test Suite">
<directory>tests/</directory>
</testsuite>
<testsuite name="schema">
<file>tests/SchemaTest.php</file>
</testsuite>
<testsuite name="seeder">
<file>tests/SeederTest.php</file>
</testsuite>
<testsuite name="builder">
<file>tests/QueryBuilderTest.php</file>
<file>tests/QueryTest.php</file>
</testsuite>
<testsuite name="transaction">
<file>tests/TransactionTest.php</file>
</testsuite>
<testsuite name="model">
<file>tests/ModelTest.php</file>
<file>tests/RelationsTest.php</file>
</testsuite>
<testsuite name="relations">
<file>tests/RelationsTest.php</file>
<file>tests/EmbeddedRelationsTest.php</file>
</testsuite>
<testsuite name="mysqlrelations">
<file>tests/RelationsTest.php</file>
</testsuite>
<testsuite name="validation">
<file>tests/ValidationTest.php</file>
</testsuite>
</testsuites>
<php>
<env name="MONGODB_URI" value="mongodb://mongodb/"/>
<env name="MONGODB_DATABASE" value="unittest"/>
<env name="MYSQL_HOST" value="mysql"/>
<env name="MYSQL_PORT" value="3306"/>
<env name="MYSQL_DATABASE" value="unittest"/>
<env name="MYSQL_USERNAME" value="root"/>
<env name="SQLITE_DATABASE" value=":memory:"/>
<env name="QUEUE_CONNECTION" value="database"/>
</php>
<source>
Expand Down
2 changes: 1 addition & 1 deletion src/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ public function toMql(): array
$group['_id'][$column] = '$' . $column;

// When grouping, also add the $last operator to each grouped field,
// this mimics MySQL's behaviour a bit.
// this mimics SQL's behaviour a bit.
$group[$column] = ['$last' => '$' . $column];
}

Expand Down
118 changes: 59 additions & 59 deletions tests/HybridRelationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

namespace MongoDB\Laravel\Tests;

use Illuminate\Database\MySqlConnection;
use Illuminate\Database\SQLiteConnection;
use Illuminate\Support\Facades\DB;
use MongoDB\Laravel\Tests\Models\Book;
use MongoDB\Laravel\Tests\Models\MysqlBook;
use MongoDB\Laravel\Tests\Models\MysqlRole;
use MongoDB\Laravel\Tests\Models\MysqlUser;
use MongoDB\Laravel\Tests\Models\Role;
use MongoDB\Laravel\Tests\Models\SqlBook;
use MongoDB\Laravel\Tests\Models\SqlRole;
use MongoDB\Laravel\Tests\Models\SqlUser;
use MongoDB\Laravel\Tests\Models\User;
use PDOException;

Expand All @@ -21,90 +21,90 @@ public function setUp(): void
parent::setUp();

try {
DB::connection('mysql')->select('SELECT 1');
DB::connection('sqlite')->select('SELECT 1');
} catch (PDOException) {
$this->markTestSkipped('MySQL connection is not available.');
$this->markTestSkipped('SQLite connection is not available.');
}

MysqlUser::executeSchema();
MysqlBook::executeSchema();
MysqlRole::executeSchema();
SqlUser::executeSchema();
SqlBook::executeSchema();
SqlRole::executeSchema();
}

public function tearDown(): void
{
MysqlUser::truncate();
MysqlBook::truncate();
MysqlRole::truncate();
SqlUser::truncate();
SqlBook::truncate();
SqlRole::truncate();
}

public function testMysqlRelations()
public function testSqlRelations()
{
$user = new MysqlUser();
$this->assertInstanceOf(MysqlUser::class, $user);
$this->assertInstanceOf(MySqlConnection::class, $user->getConnection());
$user = new SqlUser();
$this->assertInstanceOf(SqlUser::class, $user);
$this->assertInstanceOf(SQLiteConnection::class, $user->getConnection());

// Mysql User
// SQL User
$user->name = 'John Doe';
$user->save();
$this->assertIsInt($user->id);

// SQL has many
$book = new Book(['title' => 'Game of Thrones']);
$user->books()->save($book);
$user = MysqlUser::find($user->id); // refetch
$user = SqlUser::find($user->id); // refetch
$this->assertCount(1, $user->books);

// MongoDB belongs to
$book = $user->books()->first(); // refetch
$this->assertEquals('John Doe', $book->mysqlAuthor->name);
$this->assertEquals('John Doe', $book->sqlAuthor->name);

// SQL has one
$role = new Role(['type' => 'admin']);
$user->role()->save($role);
$user = MysqlUser::find($user->id); // refetch
$user = SqlUser::find($user->id); // refetch
$this->assertEquals('admin', $user->role->type);

// MongoDB belongs to
$role = $user->role()->first(); // refetch
$this->assertEquals('John Doe', $role->mysqlUser->name);
$this->assertEquals('John Doe', $role->sqlUser->name);

// MongoDB User
$user = new User();
$user->name = 'John Doe';
$user->save();

// MongoDB has many
$book = new MysqlBook(['title' => 'Game of Thrones']);
$user->mysqlBooks()->save($book);
$book = new SqlBook(['title' => 'Game of Thrones']);
$user->sqlBooks()->save($book);
$user = User::find($user->_id); // refetch
$this->assertCount(1, $user->mysqlBooks);
$this->assertCount(1, $user->sqlBooks);

// SQL belongs to
$book = $user->mysqlBooks()->first(); // refetch
$book = $user->sqlBooks()->first(); // refetch
$this->assertEquals('John Doe', $book->author->name);

// MongoDB has one
$role = new MysqlRole(['type' => 'admin']);
$user->mysqlRole()->save($role);
$role = new SqlRole(['type' => 'admin']);
$user->sqlRole()->save($role);
$user = User::find($user->_id); // refetch
$this->assertEquals('admin', $user->mysqlRole->type);
$this->assertEquals('admin', $user->sqlRole->type);

// SQL belongs to
$role = $user->mysqlRole()->first(); // refetch
$role = $user->sqlRole()->first(); // refetch
$this->assertEquals('John Doe', $role->user->name);
}

public function testHybridWhereHas()
{
$user = new MysqlUser();
$otherUser = new MysqlUser();
$this->assertInstanceOf(MysqlUser::class, $user);
$this->assertInstanceOf(MySqlConnection::class, $user->getConnection());
$this->assertInstanceOf(MysqlUser::class, $otherUser);
$this->assertInstanceOf(MySqlConnection::class, $otherUser->getConnection());

//MySql User
$user = new SqlUser();
$otherUser = new SqlUser();
$this->assertInstanceOf(SqlUser::class, $user);
$this->assertInstanceOf(SQLiteConnection::class, $user->getConnection());
$this->assertInstanceOf(SqlUser::class, $otherUser);
$this->assertInstanceOf(SQLiteConnection::class, $otherUser->getConnection());

// SQL User
$user->name = 'John Doe';
$user->id = 2;
$user->save();
Expand All @@ -130,19 +130,19 @@ public function testHybridWhereHas()
new Book(['title' => 'Harry Planter']),
]);

$users = MysqlUser::whereHas('books', function ($query) {
$users = SqlUser::whereHas('books', function ($query) {
return $query->where('title', 'LIKE', 'Har%');
})->get();

$this->assertEquals(2, $users->count());

$users = MysqlUser::whereHas('books', function ($query) {
$users = SqlUser::whereHas('books', function ($query) {
return $query->where('title', 'LIKE', 'Harry%');
}, '>=', 2)->get();

$this->assertEquals(1, $users->count());

$books = Book::whereHas('mysqlAuthor', function ($query) {
$books = Book::whereHas('sqlAuthor', function ($query) {
return $query->where('name', 'LIKE', 'Other%');
})->get();

Expand All @@ -151,14 +151,14 @@ public function testHybridWhereHas()

public function testHybridWith()
{
$user = new MysqlUser();
$otherUser = new MysqlUser();
$this->assertInstanceOf(MysqlUser::class, $user);
$this->assertInstanceOf(MySqlConnection::class, $user->getConnection());
$this->assertInstanceOf(MysqlUser::class, $otherUser);
$this->assertInstanceOf(MySqlConnection::class, $otherUser->getConnection());

//MySql User
$user = new SqlUser();
$otherUser = new SqlUser();
$this->assertInstanceOf(SqlUser::class, $user);
$this->assertInstanceOf(SQLiteConnection::class, $user->getConnection());
$this->assertInstanceOf(SqlUser::class, $otherUser);
$this->assertInstanceOf(SQLiteConnection::class, $otherUser->getConnection());

// SQL User
$user->name = 'John Doe';
$user->id = 2;
$user->save();
Expand All @@ -171,18 +171,18 @@ public function testHybridWith()
$this->assertIsInt($otherUser->id);
// Clear to start
Book::truncate();
MysqlBook::truncate();
SqlBook::truncate();
// Create books
// Mysql relation
$user->mysqlBooks()->saveMany([
new MysqlBook(['title' => 'Game of Thrones']),
new MysqlBook(['title' => 'Harry Potter']),
// SQL relation
$user->sqlBooks()->saveMany([
new SqlBook(['title' => 'Game of Thrones']),
new SqlBook(['title' => 'Harry Potter']),
]);

$otherUser->mysqlBooks()->saveMany([
new MysqlBook(['title' => 'Harry Plants']),
new MysqlBook(['title' => 'Harveys']),
new MysqlBook(['title' => 'Harry Planter']),
$otherUser->sqlBooks()->saveMany([
new SqlBook(['title' => 'Harry Plants']),
new SqlBook(['title' => 'Harveys']),
new SqlBook(['title' => 'Harry Planter']),
]);
// SQL has many Hybrid
$user->books()->saveMany([
Expand All @@ -196,12 +196,12 @@ public function testHybridWith()
new Book(['title' => 'Harry Planter']),
]);

MysqlUser::with('books')->get()
SqlUser::with('books')->get()
->each(function ($user) {
$this->assertEquals($user->id, $user->books->count());
});

MysqlUser::whereHas('mysqlBooks', function ($query) {
SqlUser::whereHas('sqlBooks', function ($query) {
return $query->where('title', 'LIKE', 'Harry%');
})
->with('books')
Expand Down
4 changes: 2 additions & 2 deletions tests/Models/Book.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public function author(): BelongsTo
return $this->belongsTo(User::class, 'author_id');
}

public function mysqlAuthor(): BelongsTo
public function sqlAuthor(): BelongsTo
{
return $this->belongsTo(MysqlUser::class, 'author_id');
return $this->belongsTo(SqlUser::class, 'author_id');
}
}
4 changes: 2 additions & 2 deletions tests/Models/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public function user(): BelongsTo
return $this->belongsTo(User::class);
}

public function mysqlUser(): BelongsTo
public function sqlUser(): BelongsTo
{
return $this->belongsTo(MysqlUser::class);
return $this->belongsTo(SqlUser::class);
}
}
Loading