Skip to content

Commit

Permalink
Use single connection using DSN for testing (#2462)
Browse files Browse the repository at this point in the history
* Always use connection string in tests

* Document DSN configuration as preferred configuration method

* Update wordings

* Use matrix config instead of manually specifying builds

* Apply StyleCI fixes

* Add missing test for code coverage
  • Loading branch information
alcaeus authored Nov 14, 2022
1 parent 560e05e commit 0606fc0
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 117 deletions.
24 changes: 12 additions & 12 deletions .github/workflows/build-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ jobs:

build:
runs-on: ${{ matrix.os }}
name: PHP v${{ matrix.php }} with Mongo v${{ matrix.mongodb }}
continue-on-error: ${{ matrix.experimental }}
name: PHP v${{ matrix.php }} with MongoDB ${{ matrix.mongodb }}
strategy:
matrix:
include:
- { os: ubuntu-latest, php: 8.0, mongodb: '4.0', experimental: false }
- { os: ubuntu-latest, php: 8.0, mongodb: 4.2, experimental: false }
- { os: ubuntu-latest, php: 8.0, mongodb: 4.4, experimental: false }
- { os: ubuntu-latest, php: 8.0, mongodb: '5.0', experimental: false }
- { os: ubuntu-latest, php: 8.1, mongodb: '4.0', experimental: false }
- { os: ubuntu-latest, php: 8.1, mongodb: 4.2, experimental: false }
- { os: ubuntu-latest, php: 8.1, mongodb: 4.4, experimental: false }
- { os: ubuntu-latest, php: 8.1, mongodb: '5.0', experimental: false }
os:
- ubuntu-latest
mongodb:
- '4.0'
- '4.2'
- '4.4'
- '5.0'
php:
- '8.0'
- '8.1'
services:
mongo:
image: mongo:${{ matrix.mongodb }}
Expand Down Expand Up @@ -88,7 +88,7 @@ jobs:
run: |
./vendor/bin/phpunit --coverage-clover coverage.xml
env:
MONGO_HOST: 0.0.0.0
MONGODB_URI: 'mongodb://127.0.0.1/'
MYSQL_HOST: 0.0.0.0
MYSQL_PORT: 3307
- uses: codecov/codecov-action@v1
Expand Down
41 changes: 15 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,47 +143,36 @@ Keep in mind that these traits are not yet supported:

Configuration
-------------
You can use MongoDB either as the main database, either as a side database. To do so, add a new `mongodb` connection to `config/database.php`:

To configure a new MongoDB connection, add a new connection entry to `config/database.php`:

```php
'mongodb' => [
'driver' => 'mongodb',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', 27017),
'dsn' => env('DB_DSN'),
'database' => env('DB_DATABASE', 'homestead'),
'username' => env('DB_USERNAME', 'homestead'),
'password' => env('DB_PASSWORD', 'secret'),
'options' => [
// here you can pass more settings to the Mongo Driver Manager
// see https://www.php.net/manual/en/mongodb-driver-manager.construct.php under "Uri Options" for a list of complete parameters that you can use

'database' => env('DB_AUTHENTICATION_DATABASE', 'admin'), // required with Mongo 3+
],
],
```

For multiple servers or replica set configurations, set the host to an array and specify each server host:
The `dsn` key contains the connection string used to connect to your MongoDB deployment. The format and available options are documented in the [MongoDB documentation](https://docs.mongodb.com/manual/reference/connection-string/).

Instead of using a connection string, you can also use the `host` and `port` configuration options to have the connection string created for you.

```php
'mongodb' => [
'driver' => 'mongodb',
'host' => ['server1', 'server2', ...],
...
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', 27017),
'database' => env('DB_DATABASE', 'homestead'),
'username' => env('DB_USERNAME', 'homestead'),
'password' => env('DB_PASSWORD', 'secret'),
'options' => [
'replicaSet' => 'rs0',
'appname' => 'homestead',
],
],
```

If you wish to use a connection string instead of full key-value params, you can set it so. Check the documentation on MongoDB's URI format: https://docs.mongodb.com/manual/reference/connection-string/

```php
'mongodb' => [
'driver' => 'mongodb',
'dsn' => env('DB_DSN'),
'database' => env('DB_DATABASE', 'homestead'),
],
```
The `options` key in the connection configuration corresponds to the [`uriOptions` parameter](https://www.php.net/manual/en/mongodb-driver-manager.construct.php#mongodb-driver-manager.construct-urioptions).

Eloquent
--------
Expand Down Expand Up @@ -223,7 +212,7 @@ class Book extends Model
protected $primaryKey = 'id';
}

// Mongo will also create _id, but the 'id' property will be used for primary key actions like find().
// MongoDB will also create _id, but the 'id' property will be used for primary key actions like find().
Book::create(['id' => 1, 'title' => 'The Fault in Our Stars']);
```

Expand All @@ -238,7 +227,7 @@ class Book extends Model
}
```

### Extending the Authenticable base model
### Extending the Authenticatable base model
This package includes a MongoDB Authenticatable Eloquent class `Jenssegers\Mongodb\Auth\User` that you can use to replace the default Authenticatable class `Illuminate\Foundation\Auth\User` for your `User` model.

```php
Expand Down
3 changes: 1 addition & 2 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@
</testsuite>
</testsuites>
<php>
<env name="MONGO_HOST" value="mongodb"/>
<env name="MONGODB_URI" value="mongodb://127.0.0.1/" />
<env name="MONGO_DATABASE" value="unittest"/>
<env name="MONGO_PORT" value="27017"/>
<env name="MYSQL_HOST" value="mysql"/>
<env name="MYSQL_PORT" value="3306"/>
<env name="MYSQL_DATABASE" value="unittest"/>
Expand Down
5 changes: 3 additions & 2 deletions src/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public function raw($expression = null)
$results = iterator_to_array($results, false);

return $this->model->hydrate($results);
} // Convert Mongo BSONDocument to a single object.
} // Convert MongoDB BSONDocument to a single object.
elseif ($results instanceof BSONDocument) {
$results = $results->getArrayCopy();

Expand All @@ -192,7 +192,8 @@ public function raw($expression = null)
* TODO Remove if https://github.com/laravel/framework/commit/6484744326531829341e1ff886cc9b628b20d73e
* wiil be reverted
* Issue in laravel frawework https://github.com/laravel/framework/issues/27791.
* @param array $values
*
* @param array $values
* @return array
*/
protected function addUpdatedAtColumn(array $values)
Expand Down
2 changes: 1 addition & 1 deletion src/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ abstract class Model extends BaseModel
*/
public function getIdAttribute($value = null)
{
// If we don't have a value for 'id', we will use the Mongo '_id' value.
// If we don't have a value for 'id', we will use the MongoDB '_id' value.
// This allows us to work with models in a more sql-like way.
if (! $value && array_key_exists('_id', $this->attributes)) {
$value = $this->attributes['_id'];
Expand Down
127 changes: 94 additions & 33 deletions tests/ConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,101 @@ public function testDb()
$this->assertInstanceOf(Client::class, $connection->getMongoClient());
}

public function testDsnDb()
public function dataConnectionConfig(): Generator
{
$connection = DB::connection('dsn_mongodb_db');
$this->assertInstanceOf(Database::class, $connection->getMongoDB());
$this->assertInstanceOf(Client::class, $connection->getMongoClient());
yield 'Single host' => [
'expectedUri' => 'mongodb://some-host',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => 'some-host',
'database' => 'tests',
],
];

yield 'Host and port' => [
'expectedUri' => 'mongodb://some-host:12345',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => 'some-host',
'port' => 12345,
'database' => 'tests',
],
];

yield 'Port in host name takes precedence' => [
'expectedUri' => 'mongodb://some-host:12345',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => 'some-host:12345',
'port' => 54321,
'database' => 'tests',
],
];

yield 'Multiple hosts' => [
'expectedUri' => 'mongodb://host-1,host-2',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => ['host-1', 'host-2'],
'database' => 'tests',
],
];

yield 'Multiple hosts with same port' => [
'expectedUri' => 'mongodb://host-1:12345,host-2:12345',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => ['host-1', 'host-2'],
'port' => 12345,
'database' => 'tests',
],
];

yield 'Multiple hosts with port' => [
'expectedUri' => 'mongodb://host-1:12345,host-2:54321',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => ['host-1:12345', 'host-2:54321'],
'database' => 'tests',
],
];

yield 'DSN takes precedence over host/port config' => [
'expectedUri' => 'mongodb://some-host:12345/auth-database',
'expectedDatabaseName' => 'tests',
'config' => [
'dsn' => 'mongodb://some-host:12345/auth-database',
'host' => 'wrong-host',
'port' => 54321,
'database' => 'tests',
],
];

yield 'Database is extracted from DSN if not specified' => [
'expectedUri' => 'mongodb://some-host:12345/tests',
'expectedDatabaseName' => 'tests',
'config' => [
'dsn' => 'mongodb://some-host:12345/tests',
],
];
}

/** @dataProvider dataConnectionConfig */
public function testConnectionConfig(string $expectedUri, string $expectedDatabaseName, array $config): void
{
$connection = new Connection($config);
$client = $connection->getMongoClient();

$this->assertSame($expectedUri, (string) $client);
$this->assertSame($expectedDatabaseName, $connection->getMongoDB()->getDatabaseName());
}

public function testConnectionWithoutConfiguredDatabase(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Database is not properly configured.');

new Connection(['dsn' => 'mongodb://some-host']);
}

public function testCollection()
Expand Down Expand Up @@ -89,33 +179,4 @@ public function testDriverName()
$driver = DB::connection('mongodb')->getDriverName();
$this->assertEquals('mongodb', $driver);
}

public function testAuth()
{
$host = Config::get('database.connections.mongodb.host');
Config::set('database.connections.mongodb.username', 'foo');
Config::set('database.connections.mongodb.password', 'bar');
Config::set('database.connections.mongodb.options.database', 'custom');

$connection = DB::connection('mongodb');
$this->assertEquals('mongodb://'.$host.'/custom', (string) $connection->getMongoClient());
}

public function testCustomHostAndPort()
{
Config::set('database.connections.mongodb.host', 'db1');
Config::set('database.connections.mongodb.port', 27000);

$connection = DB::connection('mongodb');
$this->assertEquals('mongodb://db1:27000', (string) $connection->getMongoClient());
}

public function testHostWithPorts()
{
Config::set('database.connections.mongodb.port', 27000);
Config::set('database.connections.mongodb.host', ['db1:27001', 'db2:27002', 'db3:27000']);

$connection = DB::connection('mongodb');
$this->assertEquals('mongodb://db1:27001,db2:27002,db3:27000', (string) $connection->getMongoClient());
}
}
16 changes: 0 additions & 16 deletions tests/DsnTest.php

This file was deleted.

8 changes: 3 additions & 5 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class TestCase extends Orchestra\Testbench\TestCase
/**
* Get application providers.
*
* @param \Illuminate\Foundation\Application $app
* @param \Illuminate\Foundation\Application $app
* @return array
*/
protected function getApplicationProviders($app)
Expand All @@ -24,7 +24,7 @@ protected function getApplicationProviders($app)
/**
* Get package providers.
*
* @param \Illuminate\Foundation\Application $app
* @param \Illuminate\Foundation\Application $app
* @return array
*/
protected function getPackageProviders($app)
Expand All @@ -40,7 +40,7 @@ protected function getPackageProviders($app)
/**
* Define environment setup.
*
* @param Illuminate\Foundation\Application $app
* @param Illuminate\Foundation\Application $app
* @return void
*/
protected function getEnvironmentSetUp($app)
Expand All @@ -56,8 +56,6 @@ protected function getEnvironmentSetUp($app)
$app['config']->set('database.connections.mysql', $config['connections']['mysql']);
$app['config']->set('database.connections.mongodb', $config['connections']['mongodb']);
$app['config']->set('database.connections.mongodb2', $config['connections']['mongodb']);
$app['config']->set('database.connections.dsn_mongodb', $config['connections']['dsn_mongodb']);
$app['config']->set('database.connections.dsn_mongodb_db', $config['connections']['dsn_mongodb_db']);

$app['config']->set('auth.model', 'User');
$app['config']->set('auth.providers.users.model', 'User');
Expand Down
22 changes: 2 additions & 20 deletions tests/config/database.php
Original file line number Diff line number Diff line change
@@ -1,35 +1,18 @@
<?php

$mongoHost = env('MONGO_HOST', 'mongodb');
$mongoPort = env('MONGO_PORT') ? (int) env('MONGO_PORT') : 27017;
$mysqlPort = env('MYSQL_PORT') ? (int) env('MYSQL_PORT') : 3306;

return [

'connections' => [

'mongodb' => [
'name' => 'mongodb',
'driver' => 'mongodb',
'host' => $mongoHost,
'dsn' => env('MONGODB_URI', 'mongodb://127.0.0.1/'),
'database' => env('MONGO_DATABASE', 'unittest'),
],

'dsn_mongodb' => [
'driver' => 'mongodb',
'dsn' => "mongodb://$mongoHost:$mongoPort",
'database' => env('MONGO_DATABASE', 'unittest'),
],

'dsn_mongodb_db' => [
'driver' => 'mongodb',
'dsn' => "mongodb://$mongoHost:$mongoPort/".env('MONGO_DATABASE', 'unittest'),
],

'mysql' => [
'driver' => 'mysql',
'host' => env('MYSQL_HOST', 'mysql'),
'port' => $mysqlPort,
'port' => env('MYSQL_PORT') ? (int) env('MYSQL_PORT') : 3306,
'database' => env('MYSQL_DATABASE', 'unittest'),
'username' => env('MYSQL_USERNAME', 'root'),
'password' => env('MYSQL_PASSWORD', ''),
Expand All @@ -38,5 +21,4 @@
'prefix' => '',
],
],

];

0 comments on commit 0606fc0

Please sign in to comment.