Mongo2Go is a managed wrapper around the latest MongoDB binaries. It targets .NET Standard 2.0. This Nuget package contains the executables of mongod, mongoimport and mongoexport v4.4.4 for Windows, Linux and macOS. Mongo2Go has two use cases: 1. Providing multiple, temporary and isolated MongoDB databases for unit tests (or to be precise: integration tests) 2. Providing a quick to set up MongoDB database for a local developer environment


Keywords
Mongo, MongoDB, integration, runner, test, unit, c-sharp, dotnet, dotnet-core, dotnet-standard, mongoexport, mongoimport
License
MIT
Install
Install-Package Mongo2Go -Version 3.1.3

Documentation

Mongo2Go - MongoDB for integration tests & local debugging

Logo

Build status Windows Build (Windows Server 2016)

Mongo2Go is a managed wrapper around the latest MongoDB binaries. It targets .NET Standard 2.0 (and .NET 4.6 for legacy environments) and works with Windows, Linux and macOS. This Nuget package contains the executables of mongod, mongoimport and mongoexport for Windows, Linux and macOS .

Brought to you by Johannes Hoppe, follow him on Twitter.

Mongo2Go has two use cases:

  1. Providing multiple, temporary and isolated MongoDB databases for unit tests (or to be precise: integration tests)
  2. Providing a quick to set up MongoDB database for a local developer environment

Unit Test / Integration test

With each call of the static method MongoDbRunner.Start() a new MongoDB instance will be set up. A free port will be used (starting with port 27018) and a corresponding data directory will be created. The method returns an instance of MongoDbRunner, which implements IDisposable. As soon as the MongoDbRunner is disposed (or if the Finalizer is called by the GC), the wrapped MongoDB process will be killed and all data in the data directory will be deleted.

Local debugging

In this mode a single MongoDB instance will be started on the default port (27017). No data will be deleted and the MongoDB instance won’t be killed automatically. Multiple calls to MongoDbRunner.StartForDebugging() will return an instance with the State “AlreadyRunning”. You can ignore the IDisposable interface, as it won’t have any effect. I highly recommend to not use this mode on productive machines! Here you should set up a MongoDB as it is described in the manual. For you convenience the MongoDbRunner also exposes mongoexport and mongoimport which allow you to quickly set up a working environment.

Single server replica set mode to enable transactions

MongoDbRunner.Start() can be set up to take in an optional boolean parameter called singleNodeReplSet. When passed in with the value true - (MongoDbRunner.Start(singleNodeReplSet: true))

  • a single node mongod instance will be started as a replica set with the name singleNodeReplSet. Replica set mode is required for transactions to work in MongoDB 4.0 or greater

Replica set initialization requires the use of a short delay to allow for the replica set to stabilize. This delay is linked to a timeout value of 5 seconds.

If the timeout expires before the replica set has stabilized a TimeoutException will be thrown.

The default timeout can be changed through the optional parameter singleNodeReplSetWaitTimeout, which allows values between 0 and 65535 seconds: MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 10)

Additional mongod arguments

MongoDbRunner.Start() can be set up to consume additional mongod arguments. This can be done using the string parameter called additionalMongodArguments.

The list of additional arguments cannot contain arguments already defined internally by Mongo2Go. An ArgumentException will be thrown in this case, specifying which additional arguments are required to be discarded.

Example of usage of the additional mongod arguments: MongoDbRunner.Start(additionalMongodArguments: "--quiet")

Installation

The Mongo2Go Nuget package can be found at https://nuget.org/packages/Mongo2Go/

Search for „Mongo2Go“ in the Manage NuGet Packages dialog box or run:

PM> Install-Package Mongo2Go

or run for the deprecated .NET Standard 1.6 package:

PM> Install-Package Mongo2Go -Version 2.2.16

or run for the legacy .NET 4.6 package:

PM> Install-Package Mongo2Go -Version 1.1.0

in the Package Manager Console.

  • The new 3.x branch targets .NET Standard 2.1. Please use this version if possible.
  • The old 2.x branch targets .NET Standard 1.6. No new features will be added, only bugfixes might be made.
  • The old 1.x branch targets good-old classic .NET 4.6.1. This is for legacy environments only. No changes will be made.

Examples

Example: Integration Test (here: Machine.Specifications & Fluent Assertions)

[Subject("Runner Integration Test")]
public class when_using_the_inbuild_serialization : MongoIntegrationTest
{
    static TestDocument findResult;
    
    Establish context = () =>
        {
            CreateConnection();
            _collection.Insert(TestDocument.DummyData1());
        };

    Because of = () => findResult = _collection.FindOneAs<TestDocument>();

    It should_return_a_result = () => findResult.ShouldNotBeNull();
    It should_hava_expected_data = () => findResult.ShouldHave().AllPropertiesBut(d => d.Id).EqualTo(TestDocument.DummyData1());

    Cleanup stuff = () => _runner.Dispose();
}

public class MongoIntegrationTest
{
    internal static MongoDbRunner _runner;
    internal static MongoCollection<TestDocument> _collection;

    internal static void CreateConnection()
    {
        _runner = MongoDbRunner.Start();
        
        MongoClient client = new MongoClient(_runner.ConnectionString);
        MongoDatabase database = client.GetDatabase("IntegrationTest");
        _collection = database.GetCollection<TestDocument>("TestCollection");
    }
}    

More tests can be found at https://github.com/Mongo2Go/Mongo2Go/tree/master/src/Mongo2GoTests/Runner

Example: Exporting seed data

using (MongoDbRunner runner = MongoDbRunner.StartForDebugging()) {

    runner.Export("TestDatabase", "TestCollection", @"..\..\App_Data\test.json");
}

Example: Importing for local debugging (compatible with ASP.NET MVC 4 Web API as well as ASP.NET Core)

public class WebApiApplication : System.Web.HttpApplication
{
    private MongoDbRunner _runner;

    protected void Application_Start()
    {
        _runner = MongoDbRunner.StartForDebugging();
        _runner.Import("TestDatabase", "TestCollection", @"..\..\App_Data\test.json", true);

        MongoClient client = new MongoClient(_runner.ConnectionString);
        MongoDatabase database = client.GetDatabase("TestDatabase");
        MongoCollection<TestObject> collection = database.GetCollection<TestObject>("TestCollection");

        /* happy coding! */
    }

    protected void Application_End()
    {
        _runner.Dispose();
    }
}

Example: Transactions (New feature since v2.2.8)

Full integration test with transaction handling (click to show)
 public class when_transaction_completes : MongoTransactionTest
    {
        private static TestDocument mainDocument;
        private static TestDocument dependentDocument;
        Establish context = () =>

        {
            _runner = MongoDbRunner.Start(singleNodeReplSet: true);
             client = new MongoClient(_runner.ConnectionString);
            database = client.GetDatabase(_databaseName);
            _mainCollection = database.GetCollection<TestDocument>(_mainCollectionName);
            _dependentCollection = database.GetCollection<TestDocument>(_dependentCollectionName);
            _mainCollection.InsertOne(TestDocument.DummyData2());
            _dependentCollection.InsertOne(TestDocument.DummyData2());
        };

        private Because of = () =>
        {
            var filter = Builders<TestDocument>.Filter.Where(x => x.IntTest == 23);
            var update = Builders<TestDocument>.Update.Inc(i => i.IntTest, 10);

            using (var sessionHandle = client.StartSession())
            {
                try
                {
                    var i = 0;
                    while (i < 10)
                    {
                        try
                        {
                            i++;
                            sessionHandle.StartTransaction(new TransactionOptions(
                                readConcern: ReadConcern.Local,
                                writeConcern: WriteConcern.W1)); 
                            try
                            {
                                var first = _mainCollection.UpdateOne(sessionHandle, filter, update);
                                var second = _dependentCollection.UpdateOne(sessionHandle, filter, update);
                            }
                            catch (Exception e)
                            {
                                sessionHandle.AbortTransaction();
                                throw;
                            }

                            var j = 0;
                            while (j < 10)
                            {
                                try
                                {
                                    j++;
                                    sessionHandle.CommitTransaction();
                                    break;
                                }
                                catch (MongoException e)
                                {
                                    if (e.HasErrorLabel("UnknownTransactionCommitResult"))
                                        continue;
                                    throw;
                                }
                            }
                            break;
                        }
                        catch (MongoException e)
                        {
                            if (e.HasErrorLabel("TransientTransactionError"))
                                continue;
                            throw;
                        }
                    }
                }
                catch (Exception e)
                {
                    //failed after multiple attempts so log and do what is appropriate in your case
                }
            }

             mainDocument = _mainCollection.FindSync(Builders<TestDocument>.Filter.Empty).FirstOrDefault();
             dependentDocument = _dependentCollection.FindSync(Builders<TestDocument>.Filter.Empty).FirstOrDefault();
        };
        
        It main_should_be_33 = () => mainDocument.IntTest.Should().Be(33);
        It dependent_should_be_33 = () => dependentDocument.IntTest.Should().Be(33);
        Cleanup cleanup = () => _runner.Dispose();
    }

Example: Logging with ILogger

Wire mongod's logs at info and above levels to a custom `ILogger` (click to show)
public class MongoIntegrationTest
{
    internal static MongoDbRunner _runner;

    internal static void CreateConnection()
    {
        // Create a custom logger. 
        // Replace this code with your own configuration of an ILogger.
        var provider = new ServiceCollection()
            .AddLogging(config =>
            {
                // Log to a simple console and to event logs.
                config.AddSimpleConsole();
                config.AddEventLog();
            })
            .BuildServiceProvider();
        var logger = provider.GetSerivce<ILoggerFactory>().CreateLogger("Mongo2Go");

        _runner = MongoDbRunner.Start(logger: logger);
    }
}    
Wire mongod's logs at debug levels to a custom `ILogger` (click to show)
public class MongoIntegrationTest
{
    internal static MongoDbRunner _runner;

    internal static void CreateConnection()
    {
        // Create a custom logger. 
        // Replace this code with your own configuration of an ILogger.
        var provider = new ServiceCollection()
            .AddLogging(config =>
            {
                // Mongod's D1-D2 levels are logged with Debug level.
                // D3-D5 levels are logged with Trace level.
                config.SetMinimumLevel(LogLevel.Trace);

                // Log to System.Diagnostics.Debug and to the event source.
                config.AddDebug();
                config.AddEventSourceLogger();
            })
            .BuildServiceProvider();
        var logger = provider.GetSerivce<ILoggerFactory>().CreateLogger("Mongo2Go");

        _runner = MongoDbRunner.Start(
            additionalMongodArguments: "vvvvv", // Tell mongod to output its D5 level logs
            logger: logger);
    }
}    

Changelog

Mongo2Go 3.1.3, April 30 2021

  • targeting .NET Standard 2.0 instead of 2.1, this makes Mongo2Go compatible with .NET Framework (version 4.7.1 and later) (PR #118 - many thanks to Cédric Luthi)
  • fixes handling of the path search for the NUGET_PACKAGE environment variable (PR #119 - many thanks to Timm Hoffmeister)
  • internal: dotnet pack is now used to create the nupkg file for a release (PR #121 - many thanks to Cédric Luthi)

Mongo2Go 3.1.1, April 08 2021

  • internal: Better algorithm for determining a free port. This allows parallel execution of tests and increases compatibility with Raider and other test runners. (PR #116, fixes #115 and #106 - many thanks to liangshiwei)

Mongo2Go 3.1.0, April 07 2021

  • NEW: Configurable logging! adds the option to inject a Microsoft.Extensions.Logging.ILogger to MongoDbRunner.Start(logger) arguments. Now you can adjust or disable the console output to avoid noise in CI environments. Please note the two examples shown above. (PR #113, fixes #94, #95 and #113 - many thanks to Corentin Altepe)
  • internal: replaces --sslMode disabled (deprecated) with --tlsMode disabled in command line arguments to mongod.

Mongo2Go 3.0.0, March 26 2021

  • includes MongoDB binaries of version 4.4.4 with support for Windows, Linux and macOS

  • targets .NET Standard 2.1 (can be used with .NET Core 3.0 and .NET 5.0)

  • adds new MongoDownloader tool (PR #109, fixes #82 and #112 - many thanks to Cédric Luthi)

  • adds support for NUGET_PACKAGES environment variable (PR #110 - many thanks to Bastian Eicher)

Changelog v2.0.0-alpha1 to v2.2.16 (click to show)

Mongo2Go 2.2.16, December 13 2020

  • fix for non existing starting path for binary search (PR #107, fixes #105 - many thanks to Gurov Yury)

Mongo2Go 2.2.15, December 12 2020

  • throw exception if cluster is not ready for transactions after singleNodeReplSetWaitTimeout (PR #103 - many thanks for the continued support by José Mira) s

Mongo2Go 2.2.14, October 17 2020

  • fixes a bug with pulling mongo binaries from wrong version (PR #87, fixes #86 - many thanks to mihevc)
  • ensures transaction is ready (solves error message: System.NotSupportedException : StartTransaction cannot determine if transactions are supported because there are no connected servers.) (PR #101, fixes #89, #91 and #100 - many thanks to liangshiwei)

Mongo2Go 2.2.12, September 07 2019

  • performance: waits for replica set ready log message, or throws if timeout expires, instead of using Thread.Sleep(5000) (PR #83, fixes #80 - many thanks again to José Mira)

Mongo2Go 2.2.11, May 10 2019

  • allows additional custom MongoDB arguments (PR #69, fixes #68 - many thanks to José Mira)
  • adds option to set port for StartForDebugging() (PR #72, fixes #71 - many thanks to Danny Bies)

Mongo2Go 2.2.9, February 04 2019

  • fixes a file path issue on Linux if you run on an SDK version beyond .NET Standard 1.6 (PR #63, fixes #62 and #61) - many thanks to Jeroen Vannevel)
  • continuous integration runs on Linux (Travis CI) and Windows (AppVeyor) now

Mongo2Go 2.2.8, October 12 2018

  • updated MongoDB binaries to 4.0.2 to support tests leveraging transaction across different collections and databases
  • updated MongoDB C# driver to 2.7.0 to be compatible with MongoDB 4.0
  • adds singleNodeReplSet paramter to MongoDbRunner.Start which allows mongod instance to be started as a replica set to enable transaction support (PR #57 - many thanks to Mahi Satyanarayana)
  • fixes port lookup for UnixPortWatcher (PR #58 - many thanks to Viktor Kolybaba)

Mongo2Go 2.2.7, August 13 2018

  • updates the MongoBinaryLocator to look for binaries in the nuget cache if they are not found in the project directory.
    • this will make Mongo2Go compatible with projects using the nuget PackageReference option. (PR #56, fixes #39 and #55)
  • adds the binariesSearchDirectory parameter to MongoDbRunner.Start which allows an additional binaries search directory to be provided.
    • this will make the db runner more flexible if someone decides to use it in some unpredictable way.
  • many thanks to Nicholas Markkula

Mongo2Go 2.2.6, July 20 2018

  • fixes broken linux support (fixes #47)

Mongo2Go 2.2.5, July 19 2018

Mongo2Go 2.2.4, June 06 2018

  • better support for TeamCity: removed MaxLevelOfRecursion limitation when searching for MongoDb binaries (PR #50, fixes #39)
  • many thanks to Stanko Culaja

Mongo2Go 2.2.2, June 05 2018

  • includes mongod, mongoimport and mongoexport v3.6.1 for Windows, Linux and macOS via PR #46, which fixes #45
  • many thanks to Joe Chan

Mongo2Go 2.2.1, November 23 2017

  • no MongoDB binaries changed, still .NET Standard 1.6
  • feature: uses temporary directory instead of good-old windows style C:\data\db by default (PR #42) - MongoDbRunner.Start() and MongoDbRunner.StartForDebugging() will now work without any extra parameters for Linux/macOS
  • bugfix: runs again on Linux/macOS, by making the binaries executable (PR #42, which fixes #37 and might also fix #43)
  • internal: Unit Tests are running again (PR #44, which fixes #31, #40)
  • internal: No hardcoded path passed to MongoDbRunner constructor (fixes 41)
  • many thanks to Per Liedman

Mongo2Go 2.2.0, August 17 2017

  • includes mongod, mongoimport and mongoexport v3.4.7 for Windows, Linux and macOS
  • targets .NET Standard 1.6 (can be used with .NET Core 1.0 / 1.1 / 2.0)
  • many thanks to Aviram Fireberger

Mongo2Go 2.1.0, March 10 2017

  • skips v2.0 to have same numbers as v1.x.
  • no MongoDB binaries changed since 2.0.0-alpha1 (still MongoDB v3.2.7 for Windows, Linux and macOS)
  • targets .NET Standard 1.6 (can be used with .NET Core 1.0 / 1.1)
  • bugfix: prevent windows firewall popup (PR #30, which fixes #21)
  • many thanks to kubal5003

Mongo2Go 1.1.0, March 10 2017 (legacy branch!)

  • no MongoDB binaries changed since v1.0 (still MongoDB v3.2.7 for Windows, Linux and macOS)
  • targets .NET 4.6.1
  • bugfix: prevent windows firewall popup (PR #29, which fixes #21)
  • many thanks to kubal5003

Mongo2Go 2.0.0-alpha1, December 19 2016

  • this version has no support for .NET Framework 4.6, please continue to use the stable package v.1.0.0
  • NEW: first support of .NET Standard 1.6 (#25)
    • many thanks to Hassaan Ahmed
    • see the Wiki for more information about .NET Core 1.0 / .NET Standard 1.6
Changelog v0.1.0 to v1.0.0 (click to show)

Mongo2Go 1.0.0, November 14 2016

  • v1.0 finally marked as stable
  • no changes to 1.0.0-beta4
  • changes since last stable version (0.2):
    • includes mongod, mongoimport and mongoexport v3.2.7 for Windows, Linux and macOS
    • support for Windows, Linux and macOS
    • uses MongoDB.Driver 2.3.0
    • requires .NET 4.6
    • various small bugfixes and improvements

Mongo2Go 1.0.0-beta4, October 24 2016

  • update to MongoDB.Driver 2.3.0 (#23)
  • upgraded to .NET 4.6
  • internal change: update MSpec as well and add MSTest Adapter for MSpec (ReSharper console runner doesn't support 4.6)
  • many thanks to Alexander Zeitler
  • please report any kind of issues here on github so that we can mark 1.0.0 as stable!

Mongo2Go 1.0.0-beta3, August 22 2016

  • feature: process windows are hidden now (#20)
  • bugfix: random folders are used for storing databases (#18)
  • many thanks to Matt Kocaj
  • please report any kind of issues here on github so that we can mark 1.0.0 as stable!

Mongo2Go 1.0.0-beta2, July 29 2016

  • fixes for bugs that were introduced by the big rewrite for cross-platform support
  • changes from pull request #14, which fixes #12, #13 and #15, many thanks to Mitch Ferrer
  • please report any kind of issues here on github so that we can mark 1.0.0 as stable!

Mongo2Go 1.0.0-beta, July 24 2016

  • 🎉 NEW: support for Linux and macOS 🎉
  • many thanks to Kristofer Linnestjerna from netclean.com for the new cross-platform support
  • includes mongod, mongoimport and mongoexport v3.2.7 for Windows, Linux and macOS
  • changes from pull request #8, #10, #11 which fixes #9
  • please report any kind of issues here on github so that we can mark 1.0.0 as stable!

Mongo2Go 0.2, May 30 2016

Mongo2Go 0.1.8, March 13 2016

  • includes mongod, mongoimport and mongoexport v3.0.10 (32bit)
  • changes from pull request #5, thanks to Aristarkh Zagorodnikov

Mongo2Go 0.1.6, July 21 2015

  • includes mongod, mongoimport and mongoexport v3.0.4 (32bit)
  • bug fix #4:
    Sometimes the runner tries to delete the database directory before the mongod process has been stopped, this throws an IOException. Now the runner waits until the mongod process has been stopped before the database directory will be deleted.
  • Thanks Sergey Zwezdin

Mongo2Go 0.1.5, July 08 2015

  • includes mongod, mongoimport and mongoexport v2.6.6 (32bit)
  • changes from pull request #3
  • new: Start and StartForDebugging methods accept an optional parameter to specify a different data directory (default is "C:\data\db")
  • many thanks to Marc

Mongo2Go 0.1.4, January 26 2015

  • includes mongod, mongoimport and mongoexport v2.6.6 (32bit)
  • changes from pull request #2
  • internal updates for testing the package (not part of the release)
    • updated MSpec package so that it would work with the latest VS and R# test runner
    • updated Mongo C# Driver, Fluent Assertions, and Moq packages to latest versions
    • fixed date handling for mongoimport and mongoexport to pass tests
  • many thanks to Jesse Sweetland

Mongo2Go 0.1.3, September 20 2012

  • includes mongod, mongoimport and mongoexport v2.2.0 (32bit)

Mongo2Go 0.1.2, August 20 2012

  • stable version
  • includes mongod, mongoimport and mongoexport v2.2.0-rc1 (32bit)

Mongo2Go 0.1.1, August 16 2012

  • second alpha version
  • includes mongod, mongoimport and mongoexport v2.2.0-rc1 (32bit)

Mongo2Go 0.1.0, August 15 2012

  • first alpha version
  • includes mongod, mongoimport and mongoexport v2.2.0-rc1 (32bit)

How to contribute

Just fork the project, make your changes send us a PR.
You can compile the project with Visual Studio 2017 and/or the .NET Core 2.0 CLI!

In the root folder, just run:

dotnet restore
dotnet build
dotnet test src/Mongo2GoTests