diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs
index 46656cc9..d0e61def 100644
--- a/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs
+++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading;
diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
index 375f186a..21e90944 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
@@ -38,6 +38,11 @@ namespace OpenIddict.Core
///
/// Provides methods allowing to manage the applications stored in the store.
///
+ ///
+ /// Applications that do not want to depend on a specific entity type can use the non-generic
+ /// instead, for which the actual entity type
+ /// is resolved at runtime based on the default entity type registered in the core options.
+ ///
/// The type of the Application entity.
public class OpenIddictApplicationManager : IOpenIddictApplicationManager where TApplication : class
{
diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
index f8f8bf93..8903999c 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
@@ -26,6 +26,11 @@ namespace OpenIddict.Core
///
/// Provides methods allowing to manage the authorizations stored in the store.
///
+ ///
+ /// Applications that do not want to depend on a specific entity type can use the non-generic
+ /// instead, for which the actual entity type
+ /// is resolved at runtime based on the default entity type registered in the core options.
+ ///
/// The type of the Authorization entity.
public class OpenIddictAuthorizationManager : IOpenIddictAuthorizationManager where TAuthorization : class
{
diff --git a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
index dd2f8d11..baa43048 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
@@ -24,6 +24,11 @@ namespace OpenIddict.Core
///
/// Provides methods allowing to manage the scopes stored in the store.
///
+ ///
+ /// Applications that do not want to depend on a specific entity type can use the non-generic
+ /// instead, for which the actual entity type
+ /// is resolved at runtime based on the default entity type registered in the core options.
+ ///
/// The type of the Scope entity.
public class OpenIddictScopeManager : IOpenIddictScopeManager where TScope : class
{
diff --git a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
index 0000bc8b..63258748 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
@@ -26,6 +26,11 @@ namespace OpenIddict.Core
///
/// Provides methods allowing to manage the tokens stored in the store.
///
+ ///
+ /// Applications that do not want to depend on a specific entity type can use the non-generic
+ /// instead, for which the actual entity type
+ /// is resolved at runtime based on the default entity type registered in the core options.
+ ///
/// The type of the Token entity.
public class OpenIddictTokenManager : IOpenIddictTokenManager where TToken : class
{
diff --git a/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs b/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs
index ce1a896a..1961adfa 100644
--- a/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs
+++ b/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs
@@ -50,14 +50,6 @@ namespace Microsoft.Extensions.DependencyInjection
return this;
}
- ///
- /// Disables initialization so that the MongoDB indexes used by OpenIddict
- /// are not automatically created the first time the stores are invoked.
- ///
- /// The .
- public OpenIddictMongoDbBuilder DisableInitialization()
- => Configure(options => options.DisableInitialization = true);
-
///
/// Configures OpenIddict to use the specified entity as the default application entity.
///
@@ -136,15 +128,6 @@ namespace Microsoft.Extensions.DependencyInjection
return Configure(options => options.AuthorizationsCollectionName = name);
}
- ///
- /// Sets the maximal duration given to the MongoDB client to initialize
- /// the database and register the indexes used by the OpenIddict entities.
- ///
- /// The timeout.
- /// The .
- public OpenIddictMongoDbBuilder SetInitializationTimeout(TimeSpan timeout)
- => Configure(options => options.InitializationTimeout = timeout);
-
///
/// Replaces the default scopes collection name (by default, openiddict.scopes).
///
diff --git a/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs b/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs
index 2cb654df..5914cfa2 100644
--- a/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs
+++ b/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs
@@ -12,19 +12,16 @@ using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
-using OpenIddict.MongoDb.Models;
namespace OpenIddict.MongoDb
{
///
/// Exposes the MongoDB database used by the OpenIddict stores.
///
- public class OpenIddictMongoDbContext : IOpenIddictMongoDbContext, IDisposable
+ public class OpenIddictMongoDbContext : IOpenIddictMongoDbContext
{
private readonly IOptionsMonitor _options;
private readonly IServiceProvider _provider;
- private readonly SemaphoreSlim _semaphore;
- private IMongoDatabase _database;
public OpenIddictMongoDbContext(
[NotNull] IOptionsMonitor options,
@@ -32,14 +29,8 @@ namespace OpenIddict.MongoDb
{
_options = options;
_provider = provider;
- _semaphore = new SemaphoreSlim(1);
}
- ///
- /// Disposes the semaphore held by this instance.
- ///
- public void Dispose() => _semaphore.Dispose();
-
///
/// Gets the .
///
@@ -49,135 +40,29 @@ namespace OpenIddict.MongoDb
///
public ValueTask GetDatabaseAsync(CancellationToken cancellationToken)
{
- if (_database != null)
- {
- return new ValueTask(_database);
- }
-
if (cancellationToken.IsCancellationRequested)
{
return new ValueTask(Task.FromCanceled(cancellationToken));
}
- async Task ExecuteAsync()
+ var database = _options.CurrentValue.Database;
+ if (database == null)
{
- var options = _options.CurrentValue;
- if (options == null)
- {
- throw new InvalidOperationException("The OpenIddict MongoDB options cannot be retrieved.");
- }
-
- if (!await _semaphore.WaitAsync(options.InitializationTimeout, cancellationToken))
- {
- throw new InvalidOperationException(new StringBuilder()
- .AppendLine("The MongoDB database couldn't be initialized within a reasonable timeframe.")
- .Append("Make sure that the MongoDB server is ready and accepts connections from this machine or use ")
- .Append("'services.AddOpenIddict().AddCore().UseMongoDb().SetInitializationTimeout()' to adjust the timeout.")
- .ToString());
- }
-
- try
- {
- var database = options.Database;
- if (database == null)
- {
- database = _provider.GetService();
- }
-
- if (database == null)
- {
- throw new InvalidOperationException(new StringBuilder()
- .AppendLine("No suitable MongoDB database service can be found.")
- .Append("To configure the OpenIddict MongoDB stores to use a specific database, use ")
- .Append("'services.AddOpenIddict().AddCore().UseMongoDb().UseDatabase()' or register an ")
- .Append("'IMongoDatabase' in the dependency injection container in 'ConfigureServices()'.")
- .ToString());
- }
-
- if (!options.DisableInitialization)
- {
- // Note: the cancellation token passed as a parameter is deliberately not used here to ensure
- // the cancellation of a single store operation doesn't prevent the indexes from being created.
- var applications = database.GetCollection(options.ApplicationsCollectionName);
- await applications.Indexes.CreateManyAsync(new[]
- {
- new CreateIndexModel(
- Builders.IndexKeys.Ascending(application => application.ClientId),
- new CreateIndexOptions
- {
- Unique = true
- }),
-
- new CreateIndexModel(
- Builders.IndexKeys.Ascending(application => application.PostLogoutRedirectUris),
- new CreateIndexOptions
- {
- Background = true
- }),
-
- new CreateIndexModel(
- Builders.IndexKeys.Ascending(application => application.RedirectUris),
- new CreateIndexOptions
- {
- Background = true
- })
- });
-
- var authorizations = database.GetCollection(options.AuthorizationsCollectionName);
- await authorizations.Indexes.CreateOneAsync(new CreateIndexModel(
- Builders.IndexKeys
- .Ascending(authorization => authorization.ApplicationId)
- .Ascending(authorization => authorization.Scopes)
- .Ascending(authorization => authorization.Status)
- .Ascending(authorization => authorization.Subject)
- .Ascending(authorization => authorization.Type),
- new CreateIndexOptions
- {
- Background = true
- }));
-
- var scopes = database.GetCollection(options.ScopesCollectionName);
- await scopes.Indexes.CreateOneAsync(new CreateIndexModel(
- Builders.IndexKeys.Ascending(scope => scope.Name),
- new CreateIndexOptions
- {
- Unique = true
- }));
-
- var tokens = database.GetCollection(options.TokensCollectionName);
- await tokens.Indexes.CreateManyAsync(new[]
- {
- new CreateIndexModel(
- Builders.IndexKeys.Ascending(token => token.ReferenceId),
- new CreateIndexOptions
- {
- PartialFilterExpression = Builders.Filter.Exists(token => token.ReferenceId),
- Unique = true
- }),
-
- new CreateIndexModel(
- Builders.IndexKeys
- .Ascending(token => token.ApplicationId)
- .Ascending(token => token.Status)
- .Ascending(token => token.Subject)
- .Ascending(token => token.Type),
- new CreateIndexOptions
- {
- Background = true
- })
- });
- }
-
- return _database = database;
- }
+ database = _provider.GetService();
+ }
- finally
- {
- _semaphore.Release();
- }
+ if (database == null)
+ {
+ return new ValueTask(Task.FromException(
+ new InvalidOperationException(new StringBuilder()
+ .AppendLine("No suitable MongoDB database service can be found.")
+ .Append("To configure the OpenIddict MongoDB stores to use a specific database, use ")
+ .Append("'services.AddOpenIddict().AddCore().UseMongoDb().UseDatabase()' or register an ")
+ .Append("'IMongoDatabase' in the dependency injection container in 'ConfigureServices()'.")
+ .ToString())));
}
- return new ValueTask(ExecuteAsync());
+ return new ValueTask(database);
}
}
}
diff --git a/src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs b/src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs
index 3ae3c5aa..7191d9fc 100644
--- a/src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs
+++ b/src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs
@@ -30,17 +30,6 @@ namespace OpenIddict.MongoDb
///
public IMongoDatabase Database { get; set; }
- ///
- /// Gets or sets a boolean indicating whether automatic initialization should be disabled.
- ///
- public bool DisableInitialization { get; set; }
-
- ///
- /// Gets or sets the maximal duration given to the MongoDB client to initialize
- /// the database and register the indexes used by the OpenIddict entities.
- ///
- public TimeSpan InitializationTimeout { get; set; } = TimeSpan.FromSeconds(30);
-
///
/// Gets or sets the name of the scopes collection (by default, openiddict.scopes).
///
diff --git a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbBuilderTests.cs b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbBuilderTests.cs
index 124161e5..fe970838 100644
--- a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbBuilderTests.cs
+++ b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbBuilderTests.cs
@@ -29,23 +29,6 @@ namespace OpenIddict.MongoDb.Tests
Assert.Equal("services", exception.ParamName);
}
- [Fact]
- public void DisableInitialization_InitializationIsCorrectlyDisabled()
- {
- // Arrange
- var services = CreateServices();
- var builder = CreateBuilder(services);
-
- // Act
- builder.DisableInitialization();
-
- // Assert
- var provider = services.BuildServiceProvider();
- var options = provider.GetRequiredService>().CurrentValue;
-
- Assert.True(options.DisableInitialization);
- }
-
[Fact]
public void ReplaceDefaultApplicationEntity_EntityIsCorrectlySet()
{
@@ -213,23 +196,6 @@ namespace OpenIddict.MongoDb.Tests
Assert.Equal("custom_collection", options.ScopesCollectionName);
}
- [Fact]
- public void SetInitializationTimeout_TimeoutIsCorrectlySet()
- {
- // Arrange
- var services = CreateServices();
- var builder = CreateBuilder(services);
-
- // Act
- builder.SetInitializationTimeout(TimeSpan.FromDays(42));
-
- // Assert
- var provider = services.BuildServiceProvider();
- var options = provider.GetRequiredService>().CurrentValue;
-
- Assert.Equal(TimeSpan.FromDays(42), options.InitializationTimeout);
- }
-
[Theory]
[InlineData(null)]
[InlineData("")]
diff --git a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs
index 82e5ac48..8e3d5d09 100644
--- a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs
+++ b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs
@@ -5,7 +5,6 @@
*/
using System;
-using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -13,7 +12,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using Moq;
-using OpenIddict.MongoDb.Models;
using Xunit;
namespace OpenIddict.MongoDb.Tests
@@ -30,7 +28,7 @@ namespace OpenIddict.MongoDb.Tests
var options = Mock.Of>();
var token = new CancellationToken(canceled: true);
- using var context = new OpenIddictMongoDbContext(options, provider);
+ var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
var exception = await Assert.ThrowsAsync(async delegate
@@ -41,76 +39,6 @@ namespace OpenIddict.MongoDb.Tests
Assert.Equal(token, exception.CancellationToken);
}
- [Fact]
- public async Task GetDatabaseAsync_ThrowsAnExceptionForNullOptions()
- {
- // Arrange
- var services = new ServiceCollection();
- var provider = services.BuildServiceProvider();
-
- var database = GetDatabase();
- var options = Mock.Of>();
-
- using var context = new OpenIddictMongoDbContext(options, provider);
-
- // Act and assert
- var exception = await Assert.ThrowsAsync(async delegate
- {
- await context.GetDatabaseAsync(CancellationToken.None);
- });
-
- Assert.Equal("The OpenIddict MongoDB options cannot be retrieved.", exception.Message);
- }
-
- [Fact]
- public async Task GetDatabaseAsync_ThrowsAnExceptionForConcurrentCallsWhenInitializationTimesOut()
- {
- // Arrange
- var services = new ServiceCollection();
- var provider = services.BuildServiceProvider();
-
- var manager = new Mock>();
- manager.Setup(mock => mock.CreateManyAsync(It.IsAny>>(), It.IsAny()))
- .Returns(async delegate
- {
- await Task.Delay(TimeSpan.FromMilliseconds(1000));
- return new[] { string.Empty };
- });
-
- var collection = new Mock>();
- collection.SetupGet(mock => mock.Indexes)
- .Returns(manager.Object);
-
- var database = GetDatabase();
- database.Setup(mock => mock.GetCollection(It.IsAny(), It.IsAny()))
- .Returns(collection.Object);
-
- var options = Mock.Of>(
- mock => mock.CurrentValue == new OpenIddictMongoDbOptions
- {
- Database = database.Object,
- InitializationTimeout = TimeSpan.FromMilliseconds(50)
- });
-
- using var context = new OpenIddictMongoDbContext(options, provider);
-
- // Act and assert
- var exception = await Assert.ThrowsAsync(delegate
- {
- return Task.WhenAll(
- context.GetDatabaseAsync(CancellationToken.None).AsTask(),
- context.GetDatabaseAsync(CancellationToken.None).AsTask(),
- context.GetDatabaseAsync(CancellationToken.None).AsTask(),
- context.GetDatabaseAsync(CancellationToken.None).AsTask());
- });
-
- Assert.Equal(new StringBuilder()
- .AppendLine("The MongoDB database couldn't be initialized within a reasonable timeframe.")
- .Append("Make sure that the MongoDB server is ready and accepts connections from this machine or use ")
- .Append("'services.AddOpenIddict().AddCore().UseMongoDb().SetInitializationTimeout()' to adjust the timeout.")
- .ToString(), exception.Message);
- }
-
[Fact]
public async Task GetDatabaseAsync_PrefersDatabaseRegisteredInOptionsToDatabaseRegisteredInDependencyInjectionContainer()
{
@@ -120,17 +48,17 @@ namespace OpenIddict.MongoDb.Tests
var provider = services.BuildServiceProvider();
- var database = GetDatabase();
+ var database = Mock.Of();
var options = Mock.Of>(
mock => mock.CurrentValue == new OpenIddictMongoDbOptions
{
- Database = database.Object
+ Database = database
});
- using var context = new OpenIddictMongoDbContext(options, provider);
+ var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
- Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None));
+ Assert.Same(database, await context.GetDatabaseAsync(CancellationToken.None));
}
[Fact]
@@ -140,14 +68,13 @@ namespace OpenIddict.MongoDb.Tests
var services = new ServiceCollection();
var provider = services.BuildServiceProvider();
- var database = GetDatabase();
var options = Mock.Of>(
mock => mock.CurrentValue == new OpenIddictMongoDbOptions
{
Database = null
});
- using var context = new OpenIddictMongoDbContext(options, provider);
+ var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
var exception = await Assert.ThrowsAsync(async delegate
@@ -170,8 +97,8 @@ namespace OpenIddict.MongoDb.Tests
var services = new ServiceCollection();
services.AddSingleton(Mock.Of());
- var database = GetDatabase();
- services.AddSingleton(database.Object);
+ var database = Mock.Of();
+ services.AddSingleton(database);
var provider = services.BuildServiceProvider();
@@ -181,138 +108,10 @@ namespace OpenIddict.MongoDb.Tests
Database = null
});
- using var context = new OpenIddictMongoDbContext(options, provider);
+ var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
- Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None));
- }
-
- [Fact]
- public async Task GetDatabaseAsync_SkipsInitializationWhenDisabled()
- {
- // Arrange
- var services = new ServiceCollection();
- var provider = services.BuildServiceProvider();
-
- var database = GetDatabase();
- var options = Mock.Of>(
- mock => mock.CurrentValue == new OpenIddictMongoDbOptions
- {
- Database = database.Object,
- DisableInitialization = true
- });
-
- using var context = new OpenIddictMongoDbContext(options, provider);
-
- // Act
- await context.GetDatabaseAsync(CancellationToken.None);
-
- // Assert
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Never());
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Never());
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Never());
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Never());
- }
-
- [Fact]
- public async Task GetDatabaseAsync_ReturnsCachedDatabase()
- {
- // Arrange
- var services = new ServiceCollection();
- var provider = services.BuildServiceProvider();
-
- var database = GetDatabase();
- var options = Mock.Of>(
- mock => mock.CurrentValue == new OpenIddictMongoDbOptions
- {
- Database = database.Object
- });
-
- using var context = new OpenIddictMongoDbContext(options, provider);
-
- // Act and assert
- Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None));
- Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None));
-
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Once());
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Once());
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Once());
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Once());
- }
-
- [Fact]
- public async Task GetDatabaseAsync_FailedInvocationDoesNotPreventFutureInvocations()
- {
- // Arrange
- var services = new ServiceCollection();
- var provider = services.BuildServiceProvider();
-
- var count = 0;
-
- var collection = new Mock>();
- collection.SetupGet(mock => mock.Indexes)
- .Returns(Mock.Of>());
-
- var database = GetDatabase();
- database.Setup(mock => mock.GetCollection(It.IsAny(), It.IsAny()))
- .Callback(() => count++)
- .Returns(delegate
- {
- if (count == 1)
- {
- throw new Exception();
- }
-
- return collection.Object;
- });
-
- var options = Mock.Of>(
- mock => mock.CurrentValue == new OpenIddictMongoDbOptions
- {
- Database = database.Object
- });
-
- using var context = new OpenIddictMongoDbContext(options, provider);
-
- // Act and assert
- await Assert.ThrowsAsync(async () => await context.GetDatabaseAsync(CancellationToken.None));
- Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None));
-
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Exactly(2));
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Once());
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Once());
- database.Verify(mock => mock.GetCollection(It.IsAny(), It.IsAny()), Times.Once());
- }
-
- private static Mock GetDatabase()
- {
- var applications = new Mock>();
- applications.SetupGet(mock => mock.Indexes)
- .Returns(Mock.Of>());
-
- var authorizations = new Mock>();
- authorizations.SetupGet(mock => mock.Indexes)
- .Returns(Mock.Of>());
-
- var scopes = new Mock>();
- scopes.SetupGet(mock => mock.Indexes)
- .Returns(Mock.Of>());
-
- var tokens = new Mock>();
- tokens.SetupGet(mock => mock.Indexes)
- .Returns(Mock.Of>());
-
- var database = new Mock();
- database.Setup(mock => mock.GetCollection(It.IsAny(), It.IsAny()))
- .Returns(applications.Object);
- database.Setup(mock => mock.GetCollection(It.IsAny(), It.IsAny()))
- .Returns(authorizations.Object);
- database.Setup(mock => mock.GetCollection(It.IsAny(), It.IsAny()))
- .Returns(scopes.Object);
- database.Setup(mock => mock.GetCollection(It.IsAny(), It.IsAny()))
- .Returns(tokens.Object);
-
- return database;
+ Assert.Same(database, await context.GetDatabaseAsync(CancellationToken.None));
}
}
}