206 lines
9.6 KiB
Markdown
206 lines
9.6 KiB
Markdown
<!-- omit from toc -->
|
|
# EphemeralMongo
|
|
|
|
[](https://github.com/asimmon/ephemeral-mongo/actions/workflows/ci.yml) [](https://github.com/asimmon/ephemeral-mongo/actions/workflows/release.yml)
|
|
|
|
- [About](#about)
|
|
- [Installation](#installation)
|
|
- [Usage](#usage)
|
|
- [How it works](#how-it-works)
|
|
- [MongoDB Enterprise and in-memory storage engine](#mongodb-enterprise-and-in-memory-storage-engine)
|
|
- [Windows Defender Firewall prompt](#windows-defender-firewall-prompt)
|
|
- [Reusing runners across tests](#reusing-runners-across-tests)
|
|
- [Changelog](#changelog)
|
|
|
|
## About
|
|
|
|
**EphemeralMongo** is a .NET library that provides a simple way to run temporary and disposable MongoDB servers for integration tests and local debugging, without any dependencies or external tools. It is as simple as:
|
|
|
|
```csharp
|
|
using var runner = await MongoRunner.RunAsync();
|
|
Console.WriteLine(runner.ConnectionString);
|
|
```
|
|
|
|
Use the resulting connection string to access the MongoDB server. It will automatically be stopped and cleaned up when the `runner` is disposed. You can pass options to customize the server, such as the data directory, port, and replica set configuration. More details can be found in the [usage section](#usage).
|
|
|
|
List of features and capabilities:
|
|
|
|
- Multiple ephemeral and **isolated MongoDB databases** for running tests.
|
|
- A quick way to set up a MongoDB database for a local development environment.
|
|
- Access to **MongoDB 6**, **7**, and **8**.
|
|
- Access to **MongoDB Community** and **Enterprise editions**.
|
|
- Support for **single-node replica sets**, enabling transactions and change streams.
|
|
- _mongoexport_ and _mongoimport_ tools for [exporting](https://www.mongodb.com/docs/database-tools/mongoexport/) and [importing](https://docs.mongodb.com/database-tools/mongoimport/) collections.
|
|
- Support for .NET Standard 2.0, .NET Standard 2.1, .NET 8.0 and later.
|
|
- Support for Linux, macOS, and Windows.
|
|
- Supports **MongoDB C# driver version 2.x and 3.x**.
|
|
|
|
This project follows in the footsteps of [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) and expands upon its foundation.
|
|
|
|
## Installation
|
|
|
|
| Package | Description |
|
|
| --- | --- |
|
|
| [](https://www.nuget.org/packages/EphemeralMongo/) | Install this package if you use MongoDB C# driver version 3.x. |
|
|
| [](https://www.nuget.org/packages/EphemeralMongo.v2/) | Install this package if you use MongoDB C# driver version 2.x. |
|
|
|
|
## Usage
|
|
|
|
Use `MongoRunner.RunAsync()` or `MongoRunner.Run()` methods to create a disposable instance that provides access to a **MongoDB connection string**, **import**, and **export tools**. An optional `MongoRunnerOptions` parameter can be provided to customize the MongoDB server.
|
|
|
|
```csharp
|
|
// All the following properties are OPTIONAL.
|
|
var options = new MongoRunnerOptions
|
|
{
|
|
// The desired MongoDB version to download and use.
|
|
// Possible values are V6, V7 and V8. Default is V8.
|
|
Version = MongoVersion.V8,
|
|
|
|
// The desired MongoDB edition to download and use.
|
|
// Possible values are Community and Enterprise. Default is Community.
|
|
Edition = MongoEdition.Community,
|
|
|
|
// If true, the MongoDB server will run as a single-node replica set. Default is false.
|
|
UseSingleNodeReplicaSet = true,
|
|
|
|
// Additional arguments to pass to the MongoDB server. Default is null.
|
|
AdditionalArguments = ["--quiet"],
|
|
|
|
// The port on which the MongoDB server will listen.
|
|
// Default is null, which means a random available port will be assigned.
|
|
MongoPort = 27017,
|
|
|
|
// The directory where the MongoDB server will store its data.
|
|
// Default is null, which means a temporary directory will be created.
|
|
DataDirectory = "/path/to/data/",
|
|
|
|
// Provide your own MongoDB binaries in this directory.
|
|
// Default is null, which means the library will download them automatically.
|
|
BinaryDirectory = "/path/to/mongo/bin/",
|
|
|
|
// A delegate that receives the MongoDB server's standard output.
|
|
StandardOutputLogger = Console.WriteLine,
|
|
|
|
// A delegate that receives the MongoDB server's standard error output.
|
|
StandardErrorLogger = Console.WriteLine,
|
|
|
|
// Timeout for the MongoDB server to start. Default is 30 seconds.
|
|
ConnectionTimeout = TimeSpan.FromSeconds(10),
|
|
|
|
// Timeout for the replica set to be initialized. Default is 10 seconds.
|
|
ReplicaSetSetupTimeout = TimeSpan.FromSeconds(5),
|
|
|
|
// The duration for which temporary data directories will be kept.
|
|
// Ignored when you provide your own data directory. Default is 12 hours.
|
|
DataDirectoryLifetime = TimeSpan.FromDays(1),
|
|
|
|
// Override this property to provide your own HTTP transport.
|
|
// Useful when behind a proxy or firewall. Default is a shared reusable instance.
|
|
Transport = new HttpTransport(new HttpClient()),
|
|
|
|
// Delay before checking for a new version of the MongoDB server. Default is 1 day.
|
|
NewVersionCheckTimeout = TimeSpan.FromDays(2)
|
|
};
|
|
```
|
|
|
|
```csharp
|
|
// Disposing the runner will kill the MongoDB process (mongod) and delete the associated data directory
|
|
using (await var runner = MongoRunner.RunAsync(options))
|
|
{
|
|
var database = new MongoClient(runner.ConnectionString).GetDatabase("default");
|
|
|
|
// Do something with the database
|
|
database.CreateCollection("people");
|
|
|
|
// Export a collection to a file. A synchronous version is also available.
|
|
await runner.ExportAsync("default", "people", "/path/to/default.json");
|
|
|
|
// Import a collection from a file. A synchronous version is also available.
|
|
await runner.ImportAsync("default", "people", "/path/to/default.json");
|
|
}
|
|
```
|
|
|
|
## How it works
|
|
|
|
* At runtime, the MongoDB binaries (`mongod`, `mongoimport`, and `mongoexport`) are downloaded when needed (if not already present) and extracted to your local application data directory.
|
|
* Official download links are retrieved from [this JSON file](https://downloads.mongodb.org/current.json) for the server and [this JSON file](https://downloads.mongodb.org/tools/db/release.json) for the tools.
|
|
* SHA256 checksums are used to verify the integrity of the downloaded files.
|
|
* `MongoRunner.Run` or `MongoRunner.RunAsync` always starts a new `mongod` process with a random available port.
|
|
* The resulting connection string will depend on your options (`UseSingleNodeReplicaSet`).
|
|
* By default, a unique temporary data directory is used and deleted when the `runner` is disposed.
|
|
|
|
## MongoDB Enterprise and in-memory storage engine
|
|
|
|
Make sure you are allowed to use MongoDB Enterprise binaries in your projects. The [official download page](https://www.mongodb.com/try/download/enterprise) states:
|
|
|
|
> MongoDB Enterprise Server is also available free of charge for evaluation and development purposes.
|
|
|
|
The Enterprise edition provides access to the in-memory storage engine, which is faster and more efficient for tests:
|
|
|
|
```csharp
|
|
var options = new MongoRunnerOptions
|
|
{
|
|
Edition = MongoEdition.Enterprise,
|
|
AdditionalArguments = ["--storageEngine", "inMemory"],
|
|
};
|
|
|
|
using var runner = await MongoRunner.RunAsync(options);
|
|
// [...]
|
|
```
|
|
|
|
## Windows Defender Firewall prompt
|
|
|
|
On Windows, you might get a **Windows Defender Firewall prompt**.
|
|
This is because EphemeralMongo starts the `mongod.exe` process from your local app data directory, and `mongod.exe` tries to open an available port.
|
|
|
|
## Reusing runners across tests
|
|
|
|
Avoid calling `MongoRunner.Run` or `MongoRunner.RunAsync` concurrently, as this will create many `mongod` processes and make your operating system slower. Instead, try to use a single instance and reuse it - create as many databases as you need, one per test, for example.
|
|
|
|
For this, version 3.0.0 introduces a new *experimental* `PooledMongoRunner` class. Once created, you can rent and return `MongoRunner` instances. Once rented a certain number of times, new instances will be created. This way, `mongod` processes will be reused, but not too often. This will avoid uncontrolled usage of system resources.
|
|
|
|
```csharp
|
|
var options = new MongoRunnerOptions
|
|
{
|
|
Version = MongoVersion.V7,
|
|
UseSingleNodeReplicaSet = true
|
|
};
|
|
|
|
using var pool = new MongoRunnerPool(options);
|
|
|
|
var runner1 = await pool.RentAsync();
|
|
var runner2 = await pool.RentAsync();
|
|
|
|
try
|
|
{
|
|
// Same connection string, same mongod process
|
|
Console.WriteLine(runner1.ConnectionString);
|
|
Console.WriteLine(runner2.ConnectionString);
|
|
}
|
|
finally
|
|
{
|
|
pool.Return(runner1);
|
|
pool.Return(runner2);
|
|
}
|
|
|
|
// This is a new mongod process
|
|
var runner3 = await pool.RentAsync();
|
|
```
|
|
|
|
## Changelog
|
|
|
|
### 3.0.0
|
|
|
|
See [this announcement](https://github.com/asimmon/ephemeral-mongo/issues/80).
|
|
|
|
### 2.0.0
|
|
|
|
- **Breaking change**: Support for MongoDB 5.0 and 6.0 has been removed, as their [end-of-life](https://www.mongodb.com/legal/support-policy/lifecycles) has passed.
|
|
- **Breaking change**: arm64 is now the default target for macOS. The previous target was x64.
|
|
- **Breaking change**: The Linux runtime package now uses Ubuntu 22.04's MongoDB binaries instead of the 18.04 ones. OpenSSL 3.0 is now required.
|
|
- **Breaking change**: Updated the MongoDB C# driver to 2.28.0, [which now uses strong-named assemblies](https://www.mongodb.com/community/forums/t/net-driver-2-28-0-released/289745).
|
|
- Added support for MongoDB 8.0.
|
|
- Introduced data directory management to delete old data directories automatically.
|
|
- Use direct connection in replica set connection strings.
|
|
- Fixed the spelling issue in `MongoRunnerOptions.StandardOutputLogger`.
|