using System; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using AutoFixture; using CoreUnitTests.Infrastructure; using CoreUnitTests.Infrastructure.Model; using FluentAssertions; using MongoDB.Bson; using MongoDB.Driver; using MongoDbGenericRepository; using MongoDbGenericRepository.DataAccess.Update; using Moq; using Xunit; namespace CoreUnitTests.DataAccessTests.MongoDbUpdaterTests; public class UpdateOneAsyncTests : GenericTestContext { [Fact] public async Task WithDocument_ReplacesOne() { // Arrange var document = Fixture.Create(); var collection = SetupCollection(); // Act var result = await Sut.UpdateOneAsync(document); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); ReplaceOptions expectedOptions = null; collection .Verify( x => x.ReplaceOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), document, expectedOptions, CancellationToken.None), Times.Once()); } [Fact] public async Task WithDocumentAndCancellationToken_ReplacesOne() { // Arrange var document = Fixture.Create(); var token = new CancellationToken(true); var collection = SetupCollection(); // Act var result = await Sut.UpdateOneAsync(document, token); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); ReplaceOptions expectedOptions = null; collection .Verify( x => x.ReplaceOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), document, expectedOptions, token), Times.Once()); } [Fact] public async Task WithDocumentAndUpdateDefinition_ReplacesOne() { // Arrange var document = Fixture.Create(); var collection = SetupCollection(); var updateDefinition = Builders.Update.Set(x => x.Id, document.Id); // Act var result = await Sut.UpdateOneAsync(document, updateDefinition); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), updateDefinition, null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithDocumentAndUpdateDefinitionAndCancellationToken_ReplacesOne() { // Arrange var document = Fixture.Create(); var collection = SetupCollection(); var updateDefinition = Builders.Update.Set(x => x.Id, document.Id); var token = new CancellationToken(true); // Act var result = await Sut.UpdateOneAsync(document, updateDefinition, token); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), updateDefinition, null, token), Times.Once()); } [Fact] public async Task WithDocumentAndFieldExpressionAndValue_ReplacesOne() { // Arrange var document = Fixture.Create(); var value = Fixture.Create(); var collection = SetupCollection(); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync(document, fieldExpression, value); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithDocumentAndFieldExpressionAndValueAndCancellationToken_ReplacesOne() { // Arrange var document = Fixture.Create(); var value = Fixture.Create(); var collection = SetupCollection(); var token = new CancellationToken(true); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync(document, fieldExpression, value, token); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterAndFieldExpressionAndValueAndPartitionKey_ReplacesOne() { // Arrange var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(partitionKey); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( filter, fieldExpression, value, partitionKey); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterAndFieldExpressionAndValueAndCancellationToken_ReplacesOne() { // Arrange var value = Fixture.Create(); var collection = SetupCollection(); var token = new CancellationToken(true); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( filter, fieldExpression, value, cancellationToken: token); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterAndFieldExpressionAndValueAndPartitionKeyAndCancellationToken_ReplacesOne() { // Arrange var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(partitionKey); var token = new CancellationToken(true); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( filter, fieldExpression, value, partitionKey, token); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterExpressionAndFieldExpressionAndValueAndCancellationToken_ReplacesOne() { // Arrange var value = Fixture.Create(); var collection = SetupCollection(); var token = new CancellationToken(true); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( filterExpression, fieldExpression, value, cancellationToken: token); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterExpressionAndFieldExpressionAndValueAndPartitionKey_ReplacesOne() { // Arrange var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(partitionKey); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( filterExpression, fieldExpression, value, partitionKey); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterExpressionAndFieldExpressionAndValueAndPartitionKeyAndCancellationToken_ReplacesOne() { // Arrange var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(partitionKey); var token = new CancellationToken(true); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( filterExpression, fieldExpression, value, partitionKey, token); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateOneAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithClientSessionAndDocument_ReplacesOne() { // Arrange var session = MockOf(); var document = Fixture.Create(); var collection = SetupCollection(); // Act var result = await Sut.UpdateOneAsync(session.Object, document); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); ReplaceOptions expectedOptions = null; collection .Verify( x => x.ReplaceOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), document, expectedOptions, CancellationToken.None), Times.Once()); } [Fact] public async Task WithClientSessionAndDocumentAndCancellationToken_ReplacesOne() { // Arrange var session = MockOf(); var document = Fixture.Create(); var token = new CancellationToken(true); var collection = SetupCollection(); // Act var result = await Sut.UpdateOneAsync(session.Object, document, token); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); ReplaceOptions expectedOptions = null; collection .Verify( x => x.ReplaceOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), document, expectedOptions, token), Times.Once()); } [Fact] public async Task WithClientSessionAndDocumentAndUpdateDefinition_ReplacesOne() { // Arrange var session = MockOf(); var document = Fixture.Create(); var collection = SetupCollection(); var updateDefinition = Builders.Update.Set(x => x.Id, document.Id); // Act var result = await Sut.UpdateOneAsync(session.Object, document, updateDefinition); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), updateDefinition, null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithClientSessionAndDocumentAndUpdateDefinitionAndCancellationToken_ReplacesOne() { // Arrange var session = MockOf(); var document = Fixture.Create(); var collection = SetupCollection(); var updateDefinition = Builders.Update.Set(x => x.Id, document.Id); var token = new CancellationToken(true); // Act var result = await Sut.UpdateOneAsync(session.Object, document, updateDefinition, token); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), updateDefinition, null, token), Times.Once()); } [Fact] public async Task WithClientSessionAndDocumentAndFieldExpressionAndValue_ReplacesOne() { // Arrange var session = MockOf(); var document = Fixture.Create(); var value = Fixture.Create(); var collection = SetupCollection(); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync(session.Object, document, fieldExpression, value); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithClientSessionAndDocumentAndFieldExpressionAndValueAndCancellationToken_ReplacesOne() { // Arrange var session = MockOf(); var document = Fixture.Create(); var value = Fixture.Create(); var collection = SetupCollection(); var token = new CancellationToken(true); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync(session.Object, document, fieldExpression, value, token); // Assert result.Should().BeTrue(); var expectedFilter = Builders.Filter.Eq("Id", document.Id); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithClientSessionAndFilterAndFieldExpressionAndValueAndPartitionKey_ReplacesOne() { // Arrange var session = MockOf(); var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(partitionKey); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( session.Object, filter, fieldExpression, value, partitionKey); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithClientSessionAndFilterAndFieldExpressionAndValueAndCancellationToken_ReplacesOne() { // Arrange var session = MockOf(); var value = Fixture.Create(); var collection = SetupCollection(); var token = new CancellationToken(true); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( session.Object, filter, fieldExpression, value, cancellationToken: token); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithClientSessionAndFilterAndFieldExpressionAndValueAndPartitionKeyAndCancellationToken_ReplacesOne() { // Arrange var session = MockOf(); var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(partitionKey); var token = new CancellationToken(true); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( session.Object, filter, fieldExpression, value, partitionKey, token); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithClientSessionAndFilterExpressionAndFieldExpressionAndValueAndCancellationToken_ReplacesOne() { // Arrange var session = MockOf(); var value = Fixture.Create(); var collection = SetupCollection(); var token = new CancellationToken(true); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( session.Object, filterExpression, fieldExpression, value, cancellationToken: token); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithClientSessionAndFilterExpressionAndFieldExpressionAndValueAndPartitionKey_ReplacesOne() { // Arrange var session = MockOf(); var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(partitionKey); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( session.Object, filterExpression, fieldExpression, value, partitionKey); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithClientSessionAndFilterExpressionAndFieldExpressionAndValueAndPartitionKeyAndCancellationToken_ReplacesOne() { // Arrange var session = MockOf(); var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(partitionKey); var token = new CancellationToken(true); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateOneAsync( session.Object, filterExpression, fieldExpression, value, partitionKey, token); // Assert result.Should().BeTrue(); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateOneAsync( session.Object, It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } private Mock> SetupCollection(string partitionKey = null) { var replacedId = Fixture.Create(); var count = Fixture.Create(); var replaceResult = new ReplaceOneResult.Acknowledged(count, 1, BsonValue.Create(replacedId)); var updateResult = new UpdateResult.Acknowledged(count, 1, BsonValue.Create(replacedId)); var collection = MockOf>(); collection .Setup( x => x.ReplaceOneAsync( It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(replaceResult); collection .Setup( x => x.UpdateOneAsync( It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny())) .ReturnsAsync(updateResult); collection .Setup( x => x.ReplaceOneAsync( It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(replaceResult); collection .Setup( x => x.UpdateOneAsync( It.IsAny(), It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny())) .ReturnsAsync(updateResult); var dbContext = MockOf(); dbContext .Setup(x => x.GetCollection(partitionKey)) .Returns(collection.Object); return collection; } }