Skip to content

Commit e38b221

Browse files
committed
Replace Mongo2Go with EphemeralMongo
1 parent b1b321a commit e38b221

File tree

6 files changed

+112
-32
lines changed

6 files changed

+112
-32
lines changed

Diff for: Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
<BogusVersion>34.0.*</BogusVersion>
2727
<CSharpGuidelinesAnalyzerVersion>3.8.*</CSharpGuidelinesAnalyzerVersion>
2828
<CoverletVersion>6.0.*</CoverletVersion>
29+
<EphemeralMongoVersion>1.1.*</EphemeralMongoVersion>
2930
<FluentAssertionsVersion>6.12.*</FluentAssertionsVersion>
3031
<GitHubActionsTestLoggerVersion>2.3.*</GitHubActionsTestLoggerVersion>
3132
<InheritDocVersion>1.3.*</InheritDocVersion>
3233
<JetBrainsAnnotationsVersion>2023.2.*</JetBrainsAnnotationsVersion>
33-
<Mongo2GoVersion>3.1.3</Mongo2GoVersion>
3434
<SourceLinkVersion>1.1.*</SourceLinkVersion>
3535
<TestSdkVersion>17.7.*</TestSdkVersion>
3636
<XunitVersion>2.5.*</XunitVersion>

Diff for: test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs

+1-6
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,10 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations;
88
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
99
public sealed class AtomicOperationsFixture : IAsyncLifetime
1010
{
11-
internal IntegrationTestContext<TestableStartup, OperationsDbContext> TestContext { get; }
11+
internal IntegrationTestContext<TestableStartup, OperationsDbContext> TestContext { get; } = new();
1212

1313
public AtomicOperationsFixture()
1414
{
15-
TestContext = new IntegrationTestContext<TestableStartup, OperationsDbContext>
16-
{
17-
StartMongoDbInSingleNodeReplicaSetMode = true
18-
};
19-
2015
TestContext.UseController<OperationsController>();
2116

2217
TestContext.ConfigureServicesAfterStartup(services => services.AddSingleton<ResourceDefinitionHitCounter>());

Diff for: test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs

-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ public AtomicTransactionConsistencyTests(IntegrationTestContext<TestableStartup,
1919

2020
testContext.UseController<OperationsController>();
2121

22-
testContext.StartMongoDbInSingleNodeReplicaSetMode = true;
23-
2422
testContext.ConfigureServicesAfterStartup(services =>
2523
{
2624
services.AddSingleton<ResourceDefinitionHitCounter>();

Diff for: test/TestBuildingBlocks/IntegrationTestContext.cs

+5-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using System.Runtime.InteropServices;
21
using System.Text.Json;
2+
using EphemeralMongo;
33
using JetBrains.Annotations;
44
using JsonApiDotNetCore.Configuration;
55
using JsonApiDotNetCore.MongoDb.Configuration;
@@ -11,7 +11,6 @@
1111
using Microsoft.AspNetCore.TestHost;
1212
using Microsoft.Extensions.DependencyInjection;
1313
using Microsoft.Extensions.Hosting;
14-
using Mongo2Go;
1514
using MongoDB.Driver;
1615

1716
namespace TestBuildingBlocks;
@@ -32,7 +31,7 @@ public class IntegrationTestContext<TStartup, TMongoDbContextShim> : Integration
3231
where TStartup : class
3332
where TMongoDbContextShim : MongoDbContextShim
3433
{
35-
private readonly Lazy<MongoDbRunner> _runner;
34+
private readonly Lazy<IMongoRunner> _runner;
3635
private readonly Lazy<WebApplicationFactory<TStartup>> _lazyFactory;
3736
private readonly TestControllerProvider _testControllerProvider = new();
3837

@@ -49,31 +48,15 @@ protected override JsonSerializerOptions SerializerOptions
4948

5049
public WebApplicationFactory<TStartup> Factory => _lazyFactory.Value;
5150

52-
/// <summary>
53-
/// Set this to <c>true</c> to enable transactions support in MongoDB.
54-
/// </summary>
55-
public bool StartMongoDbInSingleNodeReplicaSetMode { get; set; }
56-
5751
public IntegrationTestContext()
5852
{
59-
_runner = new Lazy<MongoDbRunner>(StartMongoDb);
53+
_runner = new Lazy<IMongoRunner>(StartMongoDb);
6054
_lazyFactory = new Lazy<WebApplicationFactory<TStartup>>(CreateFactory);
6155
}
6256

63-
private MongoDbRunner StartMongoDb()
57+
private IMongoRunner StartMongoDb()
6458
{
65-
// Increasing maxTransactionLockRequestTimeoutMillis (default=5) as workaround for occasional
66-
// "Unable to acquire lock" error when running tests locally.
67-
string arguments = "--quiet --setParameter maxTransactionLockRequestTimeoutMillis=40";
68-
69-
if (!StartMongoDbInSingleNodeReplicaSetMode)
70-
{
71-
// MongoDbRunner watches console output to detect when the replica set has stabilized. So we can only fully
72-
// suppress console output if not running in this mode.
73-
arguments += RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? " --logappend --logpath NUL" : " --logpath /dev/null";
74-
}
75-
76-
return MongoDbRunner.Start(singleNodeReplSet: StartMongoDbInSingleNodeReplicaSetMode, additionalMongodArguments: arguments);
59+
return MongoRunnerProvider.Instance.Get();
7760
}
7861

7962
public void UseController<TController>()

Diff for: test/TestBuildingBlocks/MongoRunnerProvider.cs

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using EphemeralMongo;
2+
3+
#pragma warning disable AV1553 // Do not use optional parameters with default value null for strings, collections or tasks
4+
5+
namespace TestBuildingBlocks;
6+
7+
// Based on https://gist.github.com/asimmon/612b2d54f1a0d2b4e1115590d456e0be.
8+
internal sealed class MongoRunnerProvider
9+
{
10+
public static readonly MongoRunnerProvider Instance = new();
11+
12+
private readonly object _lockObject = new();
13+
private IMongoRunner? _runner;
14+
private int _useCounter;
15+
16+
private MongoRunnerProvider()
17+
{
18+
}
19+
20+
public IMongoRunner Get()
21+
{
22+
lock (_lockObject)
23+
{
24+
if (_runner == null)
25+
{
26+
var runnerOptions = new MongoRunnerOptions
27+
{
28+
// Single-node replica set mode is required for transaction support in MongoDB.
29+
UseSingleNodeReplicaSet = true,
30+
KillMongoProcessesWhenCurrentProcessExits = true,
31+
AdditionalArguments = "--quiet"
32+
};
33+
34+
_runner = MongoRunner.Run(runnerOptions);
35+
}
36+
37+
_useCounter++;
38+
return new MongoRunnerWrapper(this, _runner);
39+
}
40+
}
41+
42+
private void Detach()
43+
{
44+
lock (_lockObject)
45+
{
46+
if (_runner != null)
47+
{
48+
_useCounter--;
49+
50+
if (_useCounter == 0)
51+
{
52+
_runner.Dispose();
53+
_runner = null;
54+
}
55+
}
56+
}
57+
}
58+
59+
private sealed class MongoRunnerWrapper : IMongoRunner
60+
{
61+
private readonly MongoRunnerProvider _owner;
62+
private IMongoRunner? _underlyingMongoRunner;
63+
64+
public string ConnectionString => _underlyingMongoRunner?.ConnectionString ?? throw new ObjectDisposedException(nameof(IMongoRunner));
65+
66+
public MongoRunnerWrapper(MongoRunnerProvider owner, IMongoRunner underlyingMongoRunner)
67+
{
68+
_owner = owner;
69+
_underlyingMongoRunner = underlyingMongoRunner;
70+
}
71+
72+
public void Import(string database, string collection, string inputFilePath, string? additionalArguments = null, bool drop = false)
73+
{
74+
if (_underlyingMongoRunner == null)
75+
{
76+
throw new ObjectDisposedException(nameof(IMongoRunner));
77+
}
78+
79+
_underlyingMongoRunner.Import(database, collection, inputFilePath, additionalArguments, drop);
80+
}
81+
82+
public void Export(string database, string collection, string outputFilePath, string? additionalArguments = null)
83+
{
84+
if (_underlyingMongoRunner == null)
85+
{
86+
throw new ObjectDisposedException(nameof(IMongoRunner));
87+
}
88+
89+
_underlyingMongoRunner.Export(database, collection, outputFilePath, additionalArguments);
90+
}
91+
92+
public void Dispose()
93+
{
94+
if (_underlyingMongoRunner != null)
95+
{
96+
_underlyingMongoRunner = null;
97+
_owner.Detach();
98+
}
99+
}
100+
}
101+
}

Diff for: test/TestBuildingBlocks/TestBuildingBlocks.csproj

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@
1010
<ItemGroup>
1111
<PackageReference Include="Bogus" Version="$(BogusVersion)" />
1212
<PackageReference Include="coverlet.collector" Version="$(CoverletVersion)" PrivateAssets="All" />
13+
<PackageReference Include="EphemeralMongo.Core" Version="$(EphemeralMongoVersion)" />
14+
<PackageReference Include="EphemeralMongo6.runtime.linux-x64" Version="$(EphemeralMongoVersion)" Condition="$([MSBuild]::IsOSPlatform('Linux'))" />
15+
<PackageReference Include="EphemeralMongo6.runtime.osx-x64" Version="$(EphemeralMongoVersion)" Condition="$([MSBuild]::IsOSPlatform('OSX'))" />
16+
<PackageReference Include="EphemeralMongo6.runtime.win-x64" Version="$(EphemeralMongoVersion)" Condition="$([MSBuild]::IsOSPlatform('Windows'))" />
1317
<PackageReference Include="GitHubActionsTestLogger" Version="$(GitHubActionsTestLoggerVersion)" PrivateAssets="All" />
1418
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionsVersion)" />
1519
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(AspNetCoreVersion)" />
1620
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
17-
<PackageReference Include="Mongo2Go" Version="$(Mongo2GoVersion)" />
1821
<PackageReference Include="xunit" Version="$(XunitVersion)" />
1922
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" PrivateAssets="All" />
2023
</ItemGroup>

0 commit comments

Comments
 (0)