Хранилище BLOB-объектов Azure: имитация CloudBlobContainer

Я пытаюсь протестировать класс, который загружает файлы в хранилище BLOB-объектов Azure. Метод загрузки принимает CloudBlobContainer в качестве входных данных. При вызове _storageContainer.Object.GetBlockBlobReference() создается исключение System.NullReferenceException. Может ли кто-нибудь помочь мне издеваться над этим?

Код юниттеста:

[TestClass()]
public class BlobStorageServiceUploadUnitTest
{
    private static BlobStorageService _service;
    private static Mock<CloudBlobContainer> _storageContainer;
    private static List<FileType> _extensions;
    private static int _maxSize;

    [ClassInitialize]
    public static void Setup_Service(TestContext context)
    {
        _extensions = new List<FileType> { FileType.Image };
        _maxSize = 2048;

        _storageContainer = new Mock<CloudBlobContainer>();

        _service = new BlobStorageService(new Mock<BEntitiesContainer>().Object, _storageContainer.Object);
    }

    [TestMethod()]
    public void When_FileIsDeleted()
    {
        var file = CreateMockFile("test.jpg", 500000);
        var blob = _storageContainer.Object.GetBlockBlobReference("deleteTest.jpg");
        blob.UploadFromStream(file.Object.InputStream);

        _service.DeleteFromStorage("deleteTest.jpg");

        var blobs = _storageContainer.Object.ListBlobs();
        Assert.AreEqual(0, blobs.Count());
    }


    public Mock<HttpPostedFileBase> CreateMockFile(string fileName, int sizeInBytes)
    {
        var file = new Mock<HttpPostedFileBase>();
        var stream = new MemoryStream();
        var bmp = new Bitmap(1, 1);
        var graphics = Graphics.FromImage(bmp);
        graphics.FillRectangle(Brushes.Black, 0, 0, 1, 1);
        bmp.Save(stream, ImageFormat.Jpeg);

        file.Setup(pf => pf.InputStream).Returns(stream);
        file.Setup(f => f.FileName).Returns(fileName);
        file.Setup(f => f.ContentLength).Returns(sizeInBytes);

        return file;
    }
}

Тестируемый класс:

public class BlobStorageService : BaseRepository<User>
{
    private CloudBlobContainer _storageContainer;

    public BlobStorageService(BEntitiesContainer context, CloudBlobContainer storageContainer) : base(context)
    {
        Context = context;
        _storageContainer = storageContainer;
    }

    public void DeleteFromStorage(string fileName)
    {
        _storageContainer.GetBlockBlobReference(fileName).DeleteIfExists();
    }
}

person JelleKerkstra    schedule 10.04.2017    source источник
comment
1. Из github мы знаем, что GetBlockBlobReference поддерживается SDK для хранилища Azure 8.0. Если в вашем случае это не последняя версия, попробуйте обновить ее до последней версии. 2. Если это возможно, пожалуйста, поделитесь всем кодом (о контейнере для хранения) проекта. 3. Мы также можем использовать эмулятор хранилища Azure. для теста, и это бесплатно для нас отладки и тестирования. Тогда не нужно использовать moq.   -  person Tom Sun - MSFT    schedule 11.04.2017
comment
Я отвечу в порядке вопросов: 1. Я видел это, но не понимаю, как это приведет к работающей реализации для меня. 2. Это весь код. 3. Когда я начинаю использовать эмулятор, мой тест больше не является юнит-тестом, а становится интеграционным тестом (мой учитель очень строго придерживается этого различия).   -  person JelleKerkstra    schedule 12.04.2017
comment
Возможный дубликат Mock CloudBlobClient с AutoFac и AutoMock   -  person Palec    schedule 08.07.2019


Ответы (1)


Единственное, что вы можете сделать, это перенести операцию CloudBlobContainer в отдельный сервис с абстрактной реализацией. В этом случае вы сможете имитировать сервис и вообще не трогать классы Azure.

Например:

public interface IAzureServiceWrapper
{
    CloudBlockBlob GetBlockBlobReference(CloudBlobContainer storageContainer, string fileName);
}

public class AzureServiceWrapper : IAzureServiceWrapper
{
    public CloudBlockBlob GetBlockBlobReference(CloudBlobContainer storageContainer, string fileName)
    {
         storageContainer.GetBlockBlobReference(fileName).DeleteIfExists();
    }
}

В этом случае будет очень легко имитировать AzureServiceWrapper, и это решение решит все проблемы с использованием классов Azure в модульных тестах. Вам просто нужно использовать AzureServiceWrapper в BlobStorageService вместо CloudBlobContainer.

person Chelovek Kemerovo    schedule 17.02.2020