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 UpdateManyAsyncTests : GenericTestContext { [Fact] public async Task WithFilterAndUpdateDefinition_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var updateDefinition = Builders.Update.Set(x => x.SomeContent, value); var collection = SetupCollection(count); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); // Act var result = await Sut.UpdateManyAsync( filter, updateDefinition); // Assert result.Should().Be(count); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(updateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterAndUpdateDefinitionAndCancellationToken_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var updateDefinition = Builders.Update.Set(x => x.SomeContent, value); var collection = SetupCollection(count); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); var token = new CancellationToken(true); // Act var result = await Sut.UpdateManyAsync( filter, updateDefinition, cancellationToken: token); // Assert result.Should().Be(count); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(updateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterAndUpdateDefinitionAndPartitionKey_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var partitionKey = Fixture.Create(); var updateDefinition = Builders.Update.Set(x => x.SomeContent, value); var collection = SetupCollection(count, partitionKey); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); // Act var result = await Sut.UpdateManyAsync( filter, updateDefinition, partitionKey); // Assert result.Should().Be(count); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(updateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterAndUpdateDefinitionAndPartitionKeyAndCancellationToken_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var partitionKey = Fixture.Create(); var updateDefinition = Builders.Update.Set(x => x.SomeContent, value); var collection = SetupCollection(count, partitionKey); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); var token = new CancellationToken(true); // Act var result = await Sut.UpdateManyAsync( filter, updateDefinition, partitionKey, cancellationToken: token); // Assert result.Should().Be(count); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(updateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterAndFieldExpressionAndValue_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var collection = SetupCollection(count); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateManyAsync( filter, fieldExpression, value); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterAndFieldExpressionAndValueAndPartitionKey_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(count, partitionKey); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateManyAsync( filter, fieldExpression, value, partitionKey); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterAndFieldExpressionAndValueAndCancellationToken_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var collection = SetupCollection(count); var token = new CancellationToken(true); var filter = Builders.Filter.Eq(x => x.SomeContent, "SomeContent"); Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateManyAsync( filter, fieldExpression, value, cancellationToken: token); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterAndFieldExpressionAndValueAndPartitionKeyAndCancellationToken_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(count, 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.UpdateManyAsync( filter, fieldExpression, value, partitionKey, token); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(filter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterExpressionAndFieldExpressionAndValue_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var collection = SetupCollection(count); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateManyAsync( filterExpression, fieldExpression, value); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterExpressionAndFieldExpressionAndValueAndCancellationToken_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var collection = SetupCollection(count); var token = new CancellationToken(true); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateManyAsync( filterExpression, fieldExpression, value, cancellationToken: token); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterExpressionAndFieldExpressionAndValueAndPartitionKey_UpdatesMany() { // Arrange var value = Fixture.Create(); var partitionKey = Fixture.Create(); var count = Fixture.Create(); var collection = SetupCollection(count, partitionKey); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateManyAsync( filterExpression, fieldExpression, value, partitionKey); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterExpressionAndFieldExpressionAndValueAndPartitionKeyAndCancellationToken_UpdatesMany() { // Arrange var value = Fixture.Create(); var count = Fixture.Create(); var partitionKey = Fixture.Create(); var collection = SetupCollection(count, partitionKey); var token = new CancellationToken(true); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; Expression> fieldExpression = testDocument => testDocument.SomeContent; // Act var result = await Sut.UpdateManyAsync( filterExpression, fieldExpression, value, partitionKey, token); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterExpressionAndUpdateDefinition_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var updateDefinition = Builders.Update.Set(x => x.SomeContent, value); var collection = SetupCollection(count); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; // Act var result = await Sut.UpdateManyAsync( filterExpression, updateDefinition); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterExpressionAndUpdateDefinitionAndCancellationToken_UpdatesMany() { // Arrange var count = Fixture.Create(); var value = Fixture.Create(); var updateDefinition = Builders.Update.Set(x => x.SomeContent, value); var collection = SetupCollection(count); var token = new CancellationToken(true); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; // Act var result = await Sut.UpdateManyAsync( filterExpression, updateDefinition, cancellationToken: token); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } [Fact] public async Task WithFilterExpressionAndUpdateDefinitionAndPartitionKey_UpdatesMany() { // Arrange var value = Fixture.Create(); var partitionKey = Fixture.Create(); var updateDefinition = Builders.Update.Set(x => x.SomeContent, value); var count = Fixture.Create(); var collection = SetupCollection(count, partitionKey); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; // Act var result = await Sut.UpdateManyAsync( filterExpression, updateDefinition, partitionKey); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, CancellationToken.None), Times.Once()); } [Fact] public async Task WithFilterExpressionAndUpdateDefinitionAndPartitionKeyAndCancellationToken_UpdatesMany() { // Arrange var value = Fixture.Create(); var count = Fixture.Create(); var updateDefinition = Builders.Update.Set(x => x.SomeContent, value); var partitionKey = Fixture.Create(); var collection = SetupCollection(count, partitionKey); var token = new CancellationToken(true); Expression> filterExpression = testDocument => testDocument.SomeContent == "SomeContent"; // Act var result = await Sut.UpdateManyAsync( filterExpression, updateDefinition, partitionKey, token); // Assert result.Should().Be(count); var expectedUpdateDefinition = Builders.Update.Set(x => x.SomeContent, value); var expectedFilter = Builders.Filter.Where(filterExpression); collection .Verify( x => x.UpdateManyAsync( It.Is>(f => f.EquivalentTo(expectedFilter)), It.Is>(u => u.EquivalentTo(expectedUpdateDefinition)), null, token), Times.Once()); } private Mock> SetupCollection(long count, string partitionKey = null) { var replacedId = Fixture.Create(); var replaceResult = new ReplaceOneResult.Acknowledged(count, count, new BsonBinaryData(replacedId, GuidRepresentation.Standard)); var updateResult = new UpdateResult.Acknowledged(count, count, new BsonBinaryData(replacedId, GuidRepresentation.Standard)); var collection = MockOf>(); collection .Setup( x => x.ReplaceOneAsync( It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(replaceResult); collection .Setup( x => x.UpdateManyAsync( 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.UpdateManyAsync( 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; } }