|
|
|
@ -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<IOptionsMonitor<OpenIddictMongoDbOptions>>(); |
|
|
|
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<TaskCanceledException>(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<IOptionsMonitor<OpenIddictMongoDbOptions>>(); |
|
|
|
|
|
|
|
using var context = new OpenIddictMongoDbContext(options, provider); |
|
|
|
|
|
|
|
// Act and assert
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidOperationException>(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<IMongoIndexManager<OpenIddictMongoDbApplication>>(); |
|
|
|
manager.Setup(mock => mock.CreateManyAsync(It.IsAny<IEnumerable<CreateIndexModel<OpenIddictMongoDbApplication>>>(), It.IsAny<CancellationToken>())) |
|
|
|
.Returns(async delegate |
|
|
|
{ |
|
|
|
await Task.Delay(TimeSpan.FromMilliseconds(1000)); |
|
|
|
return new[] { string.Empty }; |
|
|
|
}); |
|
|
|
|
|
|
|
var collection = new Mock<IMongoCollection<OpenIddictMongoDbApplication>>(); |
|
|
|
collection.SetupGet(mock => mock.Indexes) |
|
|
|
.Returns(manager.Object); |
|
|
|
|
|
|
|
var database = GetDatabase(); |
|
|
|
database.Setup(mock => mock.GetCollection<OpenIddictMongoDbApplication>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>())) |
|
|
|
.Returns(collection.Object); |
|
|
|
|
|
|
|
var options = Mock.Of<IOptionsMonitor<OpenIddictMongoDbOptions>>( |
|
|
|
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<InvalidOperationException>(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<IMongoDatabase>(); |
|
|
|
var options = Mock.Of<IOptionsMonitor<OpenIddictMongoDbOptions>>( |
|
|
|
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<IOptionsMonitor<OpenIddictMongoDbOptions>>( |
|
|
|
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<InvalidOperationException>(async delegate |
|
|
|
@ -170,8 +97,8 @@ namespace OpenIddict.MongoDb.Tests |
|
|
|
var services = new ServiceCollection(); |
|
|
|
services.AddSingleton(Mock.Of<IMongoDatabase>()); |
|
|
|
|
|
|
|
var database = GetDatabase(); |
|
|
|
services.AddSingleton(database.Object); |
|
|
|
var database = Mock.Of<IMongoDatabase>(); |
|
|
|
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<IOptionsMonitor<OpenIddictMongoDbOptions>>( |
|
|
|
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<OpenIddictMongoDbApplication>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Never()); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbAuthorization>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Never()); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbScope>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Never()); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbToken>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Never()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task GetDatabaseAsync_ReturnsCachedDatabase() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var services = new ServiceCollection(); |
|
|
|
var provider = services.BuildServiceProvider(); |
|
|
|
|
|
|
|
var database = GetDatabase(); |
|
|
|
var options = Mock.Of<IOptionsMonitor<OpenIddictMongoDbOptions>>( |
|
|
|
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<OpenIddictMongoDbApplication>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Once()); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbAuthorization>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Once()); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbScope>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Once()); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbToken>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Once()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task GetDatabaseAsync_FailedInvocationDoesNotPreventFutureInvocations() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var services = new ServiceCollection(); |
|
|
|
var provider = services.BuildServiceProvider(); |
|
|
|
|
|
|
|
var count = 0; |
|
|
|
|
|
|
|
var collection = new Mock<IMongoCollection<OpenIddictMongoDbApplication>>(); |
|
|
|
collection.SetupGet(mock => mock.Indexes) |
|
|
|
.Returns(Mock.Of<IMongoIndexManager<OpenIddictMongoDbApplication>>()); |
|
|
|
|
|
|
|
var database = GetDatabase(); |
|
|
|
database.Setup(mock => mock.GetCollection<OpenIddictMongoDbApplication>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>())) |
|
|
|
.Callback(() => count++) |
|
|
|
.Returns(delegate |
|
|
|
{ |
|
|
|
if (count == 1) |
|
|
|
{ |
|
|
|
throw new Exception(); |
|
|
|
} |
|
|
|
|
|
|
|
return collection.Object; |
|
|
|
}); |
|
|
|
|
|
|
|
var options = Mock.Of<IOptionsMonitor<OpenIddictMongoDbOptions>>( |
|
|
|
mock => mock.CurrentValue == new OpenIddictMongoDbOptions |
|
|
|
{ |
|
|
|
Database = database.Object |
|
|
|
}); |
|
|
|
|
|
|
|
using var context = new OpenIddictMongoDbContext(options, provider); |
|
|
|
|
|
|
|
// Act and assert
|
|
|
|
await Assert.ThrowsAsync<Exception>(async () => await context.GetDatabaseAsync(CancellationToken.None)); |
|
|
|
Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None)); |
|
|
|
|
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbApplication>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Exactly(2)); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbAuthorization>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Once()); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbScope>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Once()); |
|
|
|
database.Verify(mock => mock.GetCollection<OpenIddictMongoDbToken>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>()), Times.Once()); |
|
|
|
} |
|
|
|
|
|
|
|
private static Mock<IMongoDatabase> GetDatabase() |
|
|
|
{ |
|
|
|
var applications = new Mock<IMongoCollection<OpenIddictMongoDbApplication>>(); |
|
|
|
applications.SetupGet(mock => mock.Indexes) |
|
|
|
.Returns(Mock.Of<IMongoIndexManager<OpenIddictMongoDbApplication>>()); |
|
|
|
|
|
|
|
var authorizations = new Mock<IMongoCollection<OpenIddictMongoDbAuthorization>>(); |
|
|
|
authorizations.SetupGet(mock => mock.Indexes) |
|
|
|
.Returns(Mock.Of<IMongoIndexManager<OpenIddictMongoDbAuthorization>>()); |
|
|
|
|
|
|
|
var scopes = new Mock<IMongoCollection<OpenIddictMongoDbScope>>(); |
|
|
|
scopes.SetupGet(mock => mock.Indexes) |
|
|
|
.Returns(Mock.Of<IMongoIndexManager<OpenIddictMongoDbScope>>()); |
|
|
|
|
|
|
|
var tokens = new Mock<IMongoCollection<OpenIddictMongoDbToken>>(); |
|
|
|
tokens.SetupGet(mock => mock.Indexes) |
|
|
|
.Returns(Mock.Of<IMongoIndexManager<OpenIddictMongoDbToken>>()); |
|
|
|
|
|
|
|
var database = new Mock<IMongoDatabase>(); |
|
|
|
database.Setup(mock => mock.GetCollection<OpenIddictMongoDbApplication>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>())) |
|
|
|
.Returns(applications.Object); |
|
|
|
database.Setup(mock => mock.GetCollection<OpenIddictMongoDbAuthorization>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>())) |
|
|
|
.Returns(authorizations.Object); |
|
|
|
database.Setup(mock => mock.GetCollection<OpenIddictMongoDbScope>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>())) |
|
|
|
.Returns(scopes.Object); |
|
|
|
database.Setup(mock => mock.GetCollection<OpenIddictMongoDbToken>(It.IsAny<string>(), It.IsAny<MongoCollectionSettings>())) |
|
|
|
.Returns(tokens.Object); |
|
|
|
|
|
|
|
return database; |
|
|
|
Assert.Same(database, await context.GetDatabaseAsync(CancellationToken.None)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|