diff --git a/sdk/storage/Azure.Storage.Blobs/api/Azure.Storage.Blobs.netstandard2.0.cs b/sdk/storage/Azure.Storage.Blobs/api/Azure.Storage.Blobs.netstandard2.0.cs index df525122b519..54fa1e066db6 100644 --- a/sdk/storage/Azure.Storage.Blobs/api/Azure.Storage.Blobs.netstandard2.0.cs +++ b/sdk/storage/Azure.Storage.Blobs/api/Azure.Storage.Blobs.netstandard2.0.cs @@ -88,11 +88,15 @@ public BlobContainerClient(System.Uri blobContainerUri, Azure.Storage.StorageSha public virtual System.Threading.Tasks.Task> ExistsAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response GetAccessPolicy(Azure.Storage.Blobs.Models.BlobRequestConditions conditions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task> GetAccessPolicyAsync(Azure.Storage.Blobs.Models.BlobRequestConditions conditions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + protected internal virtual Azure.Storage.Blobs.Specialized.AppendBlobClient GetAppendBlobClientCore(string blobName) { throw null; } public virtual Azure.Storage.Blobs.BlobClient GetBlobClient(string blobName) { throw null; } + protected internal virtual Azure.Storage.Blobs.Specialized.BlobLeaseClient GetBlobLeaseClientCore(string leaseId) { throw null; } public virtual Azure.Pageable GetBlobs(Azure.Storage.Blobs.Models.BlobTraits traits = Azure.Storage.Blobs.Models.BlobTraits.None, Azure.Storage.Blobs.Models.BlobStates states = Azure.Storage.Blobs.Models.BlobStates.None, string prefix = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.AsyncPageable GetBlobsAsync(Azure.Storage.Blobs.Models.BlobTraits traits = Azure.Storage.Blobs.Models.BlobTraits.None, Azure.Storage.Blobs.Models.BlobStates states = Azure.Storage.Blobs.Models.BlobStates.None, string prefix = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Pageable GetBlobsByHierarchy(Azure.Storage.Blobs.Models.BlobTraits traits = Azure.Storage.Blobs.Models.BlobTraits.None, Azure.Storage.Blobs.Models.BlobStates states = Azure.Storage.Blobs.Models.BlobStates.None, string delimiter = null, string prefix = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.AsyncPageable GetBlobsByHierarchyAsync(Azure.Storage.Blobs.Models.BlobTraits traits = Azure.Storage.Blobs.Models.BlobTraits.None, Azure.Storage.Blobs.Models.BlobStates states = Azure.Storage.Blobs.Models.BlobStates.None, string delimiter = null, string prefix = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + protected internal virtual Azure.Storage.Blobs.Specialized.BlockBlobClient GetBlockBlobClientCore(string blobName) { throw null; } + protected internal virtual Azure.Storage.Blobs.Specialized.PageBlobClient GetPageBlobClientCore(string blobName) { throw null; } public virtual Azure.Response GetProperties(Azure.Storage.Blobs.Models.BlobRequestConditions conditions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task> GetPropertiesAsync(Azure.Storage.Blobs.Models.BlobRequestConditions conditions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response SetAccessPolicy(Azure.Storage.Blobs.Models.PublicAccessType accessType = Azure.Storage.Blobs.Models.PublicAccessType.None, System.Collections.Generic.IEnumerable permissions = null, Azure.Storage.Blobs.Models.BlobRequestConditions conditions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -1222,6 +1226,7 @@ public BlobBaseClient(System.Uri blobUri, Azure.Storage.StorageSharedKeyCredenti public virtual System.Threading.Tasks.Task DownloadToAsync(string path, System.Threading.CancellationToken cancellationToken) { throw null; } public virtual Azure.Response Exists(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task> ExistsAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + protected internal virtual Azure.Storage.Blobs.Specialized.BlobLeaseClient GetBlobLeaseClientCore(string leaseId) { throw null; } public virtual Azure.Response GetProperties(Azure.Storage.Blobs.Models.BlobRequestConditions conditions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task> GetPropertiesAsync(Azure.Storage.Blobs.Models.BlobRequestConditions conditions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response GetTags(Azure.Storage.Blobs.Models.BlobRequestConditions conditions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } diff --git a/sdk/storage/Azure.Storage.Blobs/src/AppendBlobClient.cs b/sdk/storage/Azure.Storage.Blobs/src/AppendBlobClient.cs index 66ac87d8ab8d..0685f40e531e 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/AppendBlobClient.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/AppendBlobClient.cs @@ -1589,23 +1589,7 @@ public static AppendBlobClient GetAppendBlobClient( this BlobContainerClient client, string blobName) { - if (client.ClientSideEncryption != default) - { - throw Errors.ClientSideEncryption.TypeNotSupported(typeof(AppendBlobClient)); - } - - BlobUriBuilder blobUriBuilder = new BlobUriBuilder(client.Uri) - { - BlobName = blobName - }; - - return new AppendBlobClient( - blobUriBuilder.ToUri(), - client.Pipeline, - client.Version, - client.ClientDiagnostics, - client.CustomerProvidedKey, - client.EncryptionScope); + return client.GetAppendBlobClientCore(blobName); } } } diff --git a/sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs b/sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs index 63d9efbc7056..3a3d1b845665 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs @@ -449,6 +449,16 @@ private protected virtual BlobBaseClient WithVersionCore(string versionId) EncryptionScope); } + /// + /// Initializes a new instance of the class. + /// + /// + /// An optional lease ID. If no lease ID is provided, a random lease + /// ID will be created. + /// + protected internal virtual BlobLeaseClient GetBlobLeaseClientCore(string leaseId) => + new BlobLeaseClient(this, leaseId); + /// /// Sets the various name fields if they are currently null. /// diff --git a/sdk/storage/Azure.Storage.Blobs/src/BlobContainerClient.cs b/sdk/storage/Azure.Storage.Blobs/src/BlobContainerClient.cs index 1c4e0d0324e0..497d6d7d576f 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/BlobContainerClient.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/BlobContainerClient.cs @@ -405,6 +405,108 @@ public virtual BlobClient GetBlobClient(string blobName) EncryptionScope); } + /// + /// Create a new object by + /// concatenating to + /// the end of the . The new + /// + /// uses the same request policy pipeline as the + /// . + /// + /// The name of the block blob. + /// A new instance. + protected internal virtual BlockBlobClient GetBlockBlobClientCore(string blobName) + { + if (ClientSideEncryption != default) + { + throw Errors.ClientSideEncryption.TypeNotSupported(typeof(BlockBlobClient)); + } + + BlobUriBuilder blobUriBuilder = new BlobUriBuilder(Uri) + { + BlobName = blobName + }; + + return new BlockBlobClient( + blobUriBuilder.ToUri(), + Pipeline, + Version, + ClientDiagnostics, + CustomerProvidedKey, + EncryptionScope); + } + + /// + /// Create a new object by + /// concatenating to + /// the end of the . The new + /// + /// uses the same request policy pipeline as the + /// . + /// + /// The name of the append blob. + /// A new instance. + protected internal virtual AppendBlobClient GetAppendBlobClientCore(string blobName) + { + if (ClientSideEncryption != default) + { + throw Errors.ClientSideEncryption.TypeNotSupported(typeof(AppendBlobClient)); + } + + BlobUriBuilder blobUriBuilder = new BlobUriBuilder(Uri) + { + BlobName = blobName + }; + + return new AppendBlobClient( + blobUriBuilder.ToUri(), + Pipeline, + Version, + ClientDiagnostics, + CustomerProvidedKey, + EncryptionScope); + } + + /// + /// Create a new object by + /// concatenating to + /// the end of the . The new + /// + /// uses the same request policy pipeline as the + /// . + /// + /// The name of the page blob. + /// A new instance. + protected internal virtual PageBlobClient GetPageBlobClientCore(string blobName) + { + if (ClientSideEncryption != default) + { + throw Errors.ClientSideEncryption.TypeNotSupported(typeof(PageBlobClient)); + } + + BlobUriBuilder blobUriBuilder = new BlobUriBuilder(Uri) + { + BlobName = blobName + }; + + return new PageBlobClient( + blobUriBuilder.ToUri(), + Pipeline, + Version, + ClientDiagnostics, + CustomerProvidedKey, + EncryptionScope); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// An optional lease ID. If no lease ID is provided, a random lease + /// ID will be created. + /// + protected internal virtual BlobLeaseClient GetBlobLeaseClientCore(string leaseId) => + new BlobLeaseClient(this, leaseId); /// /// Sets the various name fields if they are currently null. diff --git a/sdk/storage/Azure.Storage.Blobs/src/BlobLeaseClient.cs b/sdk/storage/Azure.Storage.Blobs/src/BlobLeaseClient.cs index 9274b510d3ae..e5e4d73e8166 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/BlobLeaseClient.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/BlobLeaseClient.cs @@ -1185,7 +1185,7 @@ public static partial class SpecializedBlobExtensions public static BlobLeaseClient GetBlobLeaseClient( this BlobBaseClient client, string leaseId = null) => - new BlobLeaseClient(client, leaseId); + client.GetBlobLeaseClientCore(leaseId); /// /// Initializes a new instance of the class. @@ -1201,6 +1201,6 @@ public static BlobLeaseClient GetBlobLeaseClient( public static BlobLeaseClient GetBlobLeaseClient( this BlobContainerClient client, string leaseId = null) => - new BlobLeaseClient(client, leaseId); + client.GetBlobLeaseClientCore(leaseId); } } diff --git a/sdk/storage/Azure.Storage.Blobs/src/BlockBlobClient.cs b/sdk/storage/Azure.Storage.Blobs/src/BlockBlobClient.cs index faba364b571e..9efc54b086e0 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/BlockBlobClient.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/BlockBlobClient.cs @@ -2232,23 +2232,7 @@ public static BlockBlobClient GetBlockBlobClient( this BlobContainerClient client, string blobName) { - if (client.ClientSideEncryption != default) - { - throw Errors.ClientSideEncryption.TypeNotSupported(typeof(BlockBlobClient)); - } - - BlobUriBuilder blobUriBuilder = new BlobUriBuilder(client.Uri) - { - BlobName = blobName - }; - - return new BlockBlobClient( - blobUriBuilder.ToUri(), - client.Pipeline, - client.Version, - client.ClientDiagnostics, - client.CustomerProvidedKey, - client.EncryptionScope); + return client.GetBlockBlobClientCore(blobName); } } } diff --git a/sdk/storage/Azure.Storage.Blobs/src/PageBlobClient.cs b/sdk/storage/Azure.Storage.Blobs/src/PageBlobClient.cs index 64deb093e322..630e1390328b 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/PageBlobClient.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/PageBlobClient.cs @@ -3114,23 +3114,7 @@ public static PageBlobClient GetPageBlobClient( this BlobContainerClient client, string blobName) { - if (client.ClientSideEncryption != default) - { - throw Errors.ClientSideEncryption.TypeNotSupported(typeof(PageBlobClient)); - } - - BlobUriBuilder blobUriBuilder = new BlobUriBuilder(client.Uri) - { - BlobName = blobName - }; - - return new PageBlobClient( - blobUriBuilder.ToUri(), - client.Pipeline, - client.Version, - client.ClientDiagnostics, - client.CustomerProvidedKey, - client.EncryptionScope); + return client.GetPageBlobClientCore(blobName); } } } diff --git a/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs b/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs index 901cf5327fa4..db25ed3ec5e2 100644 --- a/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs +++ b/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs @@ -20,6 +20,8 @@ using Azure.Storage.Sas; using Azure.Storage.Test; using Azure.Storage.Test.Shared; +using Moq; +using Moq.Protected; using NUnit.Framework; using TestConstants = Azure.Storage.Test.TestConstants; @@ -5556,6 +5558,23 @@ public void WithVersion() Assert.AreEqual(versionUri, blobUriBuilder.ToUri()); } + [Test] + public void CanMockBlobLeaseClientRetrieval() + { + // Arrange + string leaseId = "leaseId"; + Mock blobBaseClientMock = new Mock(); + Mock blobLeaseClientMock = new Mock(); + blobBaseClientMock.Protected().Setup("GetBlobLeaseClientCore", leaseId).Returns(blobLeaseClientMock.Object); + + // Act + var blobLeaseClient = blobBaseClientMock.Object.GetBlobLeaseClient(leaseId); + + // Assert + Assert.IsNotNull(blobLeaseClient); + Assert.AreSame(blobLeaseClientMock.Object, blobLeaseClient); + } + private async Task GetNewBlobClient(BlobContainerClient container, string blobName = default) { blobName ??= GetNewBlobName(); diff --git a/sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs b/sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs index fe8857455558..fa390d89ca50 100644 --- a/sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs +++ b/sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection.Metadata; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -17,6 +16,8 @@ using Azure.Storage.Sas; using Azure.Storage.Test; using Azure.Storage.Test.Shared; +using Moq; +using Moq.Protected; using NUnit.Framework; namespace Azure.Storage.Blobs.Test @@ -2512,6 +2513,39 @@ public async Task GetBlobClients_SpecialCharacters(string blobName) Assert.AreEqual(blobName, pageBlobClientFromConnectionString.Name); } + [Test] + public void CanMockBlobClientsRetrieval() + { + // Arrange + string blobName = "test"; + string leaseId = "leaseId"; + Mock containerClientMock = new Mock(); + Mock blockBlobClientMock = new Mock(); + Mock appendBlobClientMock = new Mock(); + Mock pageBlobClientMock = new Mock(); + Mock blobLeaseClientMock = new Mock(); + containerClientMock.Protected().Setup("GetBlockBlobClientCore", blobName).Returns(blockBlobClientMock.Object); + containerClientMock.Protected().Setup("GetAppendBlobClientCore", blobName).Returns(appendBlobClientMock.Object); + containerClientMock.Protected().Setup("GetPageBlobClientCore", blobName).Returns(pageBlobClientMock.Object); + containerClientMock.Protected().Setup("GetBlobLeaseClientCore", leaseId).Returns(blobLeaseClientMock.Object); + + // Act + var blockBlobClient = containerClientMock.Object.GetBlockBlobClient(blobName); + var appendBlobClient = containerClientMock.Object.GetAppendBlobClient(blobName); + var pageBlobClient = containerClientMock.Object.GetPageBlobClient(blobName); + var blobLeaseClient = containerClientMock.Object.GetBlobLeaseClient(leaseId); + + // Assert + Assert.IsNotNull(blockBlobClient); + Assert.AreSame(blockBlobClientMock.Object, blockBlobClient); + Assert.IsNotNull(appendBlobClient); + Assert.AreSame(appendBlobClientMock.Object, appendBlobClient); + Assert.IsNotNull(pageBlobClient); + Assert.AreSame(pageBlobClientMock.Object, pageBlobClient); + Assert.IsNotNull(blobLeaseClient); + Assert.AreSame(blobLeaseClientMock.Object, blobLeaseClient); + } + #region Secondary Storage [Test] public async Task ListContainersSegmentAsync_SecondaryStorageFirstRetrySuccessful() diff --git a/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/BlobBaseClientTests/CanMockBlobLeaseClientRetrieval.json b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/BlobBaseClientTests/CanMockBlobLeaseClientRetrieval.json new file mode 100644 index 000000000000..20e5015d169f --- /dev/null +++ b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/BlobBaseClientTests/CanMockBlobLeaseClientRetrieval.json @@ -0,0 +1,4 @@ +{ + "Entries": [], + "Variables": {} +} \ No newline at end of file diff --git a/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/BlobBaseClientTests/CanMockBlobLeaseClientRetrievalAsync.json b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/BlobBaseClientTests/CanMockBlobLeaseClientRetrievalAsync.json new file mode 100644 index 000000000000..20e5015d169f --- /dev/null +++ b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/BlobBaseClientTests/CanMockBlobLeaseClientRetrievalAsync.json @@ -0,0 +1,4 @@ +{ + "Entries": [], + "Variables": {} +} \ No newline at end of file diff --git a/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/CanMockBlobClientsRetrieval.json b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/CanMockBlobClientsRetrieval.json new file mode 100644 index 000000000000..20e5015d169f --- /dev/null +++ b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/CanMockBlobClientsRetrieval.json @@ -0,0 +1,4 @@ +{ + "Entries": [], + "Variables": {} +} \ No newline at end of file diff --git a/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/CanMockBlobClientsRetrievalAsync.json b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/CanMockBlobClientsRetrievalAsync.json new file mode 100644 index 000000000000..20e5015d169f --- /dev/null +++ b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/CanMockBlobClientsRetrievalAsync.json @@ -0,0 +1,4 @@ +{ + "Entries": [], + "Variables": {} +} \ No newline at end of file