From 968ed20a83fe86c39b6cc05da261a51f071a3e9d Mon Sep 17 00:00:00 2001 From: salim ben ahben <40862545+Sben65@users.noreply.github.com> Date: Wed, 25 May 2022 16:55:26 +0200 Subject: [PATCH] Issue#741 rework exception on LoRaWANDeviceModelsController (#749) * implement #741 * implement #741 Unit test on LoRaWANDeviceModelsController --- .../LoRaWANDeviceModelsControllerTest.cs | 955 ++++++++++++++++++ 1 file changed, 955 insertions(+) create mode 100644 src/AzureIoTHub.Portal.Server.Tests.Unit/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsControllerTest.cs diff --git a/src/AzureIoTHub.Portal.Server.Tests.Unit/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsControllerTest.cs b/src/AzureIoTHub.Portal.Server.Tests.Unit/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsControllerTest.cs new file mode 100644 index 000000000..ff24528c3 --- /dev/null +++ b/src/AzureIoTHub.Portal.Server.Tests.Unit/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsControllerTest.cs @@ -0,0 +1,955 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Server.Tests.Unit.Controllers.V10.LoRaWAN +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Linq.Expressions; + using System.Threading; + using System.Threading.Tasks; + using Azure; + using Azure.Data.Tables; + using AzureIoTHub.Portal.Models.v10; + using AzureIoTHub.Portal.Models.v10.LoRaWAN; + using AzureIoTHub.Portal.Server.Controllers.V10; + using AzureIoTHub.Portal.Server.Controllers.V10.LoRaWAN; + using AzureIoTHub.Portal.Server.Exceptions; + using AzureIoTHub.Portal.Server.Factories; + using AzureIoTHub.Portal.Server.Managers; + using AzureIoTHub.Portal.Server.Mappers; + using AzureIoTHub.Portal.Server.Services; + using FluentAssertions; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Azure.Devices.Provisioning.Service; + using Microsoft.Azure.Devices.Shared; + using Microsoft.Extensions.Logging; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class LoRaWANDeviceModelsControllerTest + { + private MockRepository mockRepository; + + private Mock>> mockLogger; + private Mock mockDeviceModelImageManager; + private Mock mockDeviceModelCommandMapper; + private Mock> mockDeviceModelMapper; + private Mock mockDeviceService; + private Mock mockTableClientFactory; + private Mock mockDeviceProvisioningServiceManager; + private Mock mockDeviceTemplatesTableClient; + private Mock mockCommandsTableClient; + private Mock mockConfigService; + + [SetUp] + public void SetUp() + { + this.mockRepository = new MockRepository(MockBehavior.Strict); + + this.mockLogger = this.mockRepository.Create>>(); + this.mockDeviceModelImageManager = this.mockRepository.Create(); + this.mockDeviceModelCommandMapper = this.mockRepository.Create(); + this.mockDeviceProvisioningServiceManager = this.mockRepository.Create(); + this.mockDeviceModelMapper = this.mockRepository.Create>(); + this.mockDeviceService = this.mockRepository.Create(); + this.mockTableClientFactory = this.mockRepository.Create(); + this.mockDeviceTemplatesTableClient = this.mockRepository.Create(); + this.mockCommandsTableClient = this.mockRepository.Create(); + this.mockConfigService = this.mockRepository.Create(); + } + + private LoRaWANDeviceModelsController CreateDeviceModelsController() + { + return new LoRaWANDeviceModelsController( + this.mockLogger.Object, + this.mockDeviceModelImageManager.Object, + this.mockDeviceModelMapper.Object, + this.mockDeviceService.Object, + this.mockTableClientFactory.Object, + this.mockDeviceProvisioningServiceManager.Object, + this.mockConfigService.Object); + } + + [Test] + public void GetListShouldReturnAList() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + var returnedIndex = 10; + + var mockTableResponse = this.mockRepository.Create>(); + var mockEnumerator = this.mockRepository.Create>(); + _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); + _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => returnedIndex-- > 0); + + _ = mockEnumerator.Setup(x => x.Current) + .Returns(new TableEntity(Guid.NewGuid().ToString(), Guid.NewGuid().ToString())); + + _ = mockTableResponse.Setup(x => x.GetEnumerator()) + .Returns(mockEnumerator.Object); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) + .Returns(mockTableResponse.Object); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + _ = this.mockDeviceModelMapper.Setup(c => c.CreateDeviceModelListItem(It.IsAny())) + .Returns((TableEntity _) => new DeviceModel()); + + // Act + var response = deviceModelsController.GetItems(); + + // Assert + Assert.IsNotNull(response); + Assert.IsAssignableFrom(response.Result); + var okResponse = response.Result as OkObjectResult; + + Assert.AreEqual(200, okResponse.StatusCode); + + Assert.IsNotNull(okResponse.Value); + var result = okResponse.Value as IEnumerable; + Assert.AreEqual(10, result?.Count()); + + this.mockRepository.VerifyAll(); + } + + [Test] + public void WhenQueryFailedGetListShouldThrowAnExceptionInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) + .Throws(new RequestFailedException("request failed.")); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + // Act + var act = () => deviceModelsController.GetItems(); + + // Assert + _ = act.Should().Throw(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task GetItemShouldReturnAValue() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + var mockResponse = this.mockRepository.Create>(); + _ = mockResponse.Setup(c => c.Value).Returns(new TableEntity(Guid.NewGuid().ToString(), Guid.NewGuid().ToString())); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( + It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.Is(k => k == "test"), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(mockResponse.Object); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + _ = this.mockDeviceModelMapper.Setup(c => c.CreateDeviceModel(It.IsAny())) + .Returns((TableEntity _) => new LoRaDeviceModel()); + + // Act + var result = await deviceModelsController.GetItem("test"); + + // Assert + Assert.IsNotNull(result); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenModelNotExistsGetItemShouldReturn404() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupNotFoundEntity(); + + // Act + var response = await deviceModelsController.GetItem(Guid.NewGuid().ToString()); + + // Assert + Assert.IsNotNull(response); + Assert.IsAssignableFrom(response.Result); + + this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); + this.mockDeviceModelImageManager.VerifyAll(); + } + + [Test] + public async Task WhenGetEntityFailedOnGetItemShouldThrowInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupErrorEntity(); + + // Act + var act = () => deviceModelsController.GetItem(Guid.NewGuid().ToString()); + + // Assert + _ = await act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task GetAvatarShouldReturnTheComputedModelAvatarUri() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + var entity = SetupMockEntity(); + + var expectedUrl = new Uri($"http://fake.local/{entity.RowKey}"); + + _ = this.mockDeviceModelImageManager.Setup(c => c.ComputeImageUri(It.Is(x => x == entity.RowKey))) + .Returns(expectedUrl); + + // Act + var response = await deviceModelsController.GetAvatar(entity.RowKey); + + // Assert + Assert.IsNotNull(response); + Assert.IsAssignableFrom(response.Result); + var okResponse = response.Result as OkObjectResult; + + Assert.AreEqual(200, okResponse.StatusCode); + + Assert.IsNotNull(okResponse.Value); + Assert.AreEqual(expectedUrl, okResponse.Value.ToString()); + + this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); + this.mockDeviceModelImageManager.VerifyAll(); + } + + [Test] + public async Task WhenModelNotExistsGetAvatarShouldReturn404() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupNotFoundEntity(); + + // Act + var response = await deviceModelsController.GetAvatar(Guid.NewGuid().ToString()); + + // Assert + Assert.IsNotNull(response); + Assert.IsAssignableFrom(response.Result); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenGetEntityThrowAnErrorGetAvatarShouldThrowInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupErrorEntity(); + + // Act + var act = async () => await deviceModelsController.GetAvatar(Guid.NewGuid().ToString()); + + // Assert + _ = await act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task ChangeAvatarShouldChangeModelImageStream() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + var entity = SetupMockEntity(); + + var mockFile = this.mockRepository.Create(); + var expectedUrl = $"http://fake.local/{entity.RowKey}"; + + using var imageStream = new MemoryStream(); + + _ = mockFile.Setup(c => c.OpenReadStream()) + .Returns(imageStream); + + _ = this.mockDeviceModelImageManager.Setup(c => c.ChangeDeviceModelImageAsync( + It.Is(x => x == entity.RowKey), + It.Is(x => x == imageStream))) + .ReturnsAsync(expectedUrl); + + // Act + var response = await deviceModelsController.ChangeAvatar(entity.RowKey, mockFile.Object); + + // Assert + Assert.IsNotNull(response); + Assert.IsAssignableFrom(response.Result); + var okResponse = response.Result as OkObjectResult; + + Assert.AreEqual(200, okResponse.StatusCode); + + Assert.IsNotNull(okResponse.Value); + Assert.AreEqual(expectedUrl, okResponse.Value.ToString()); + + this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); + this.mockDeviceModelImageManager.VerifyAll(); + } + + [Test] + public async Task WhenModelNotExistsChangeAvatarShouldReturn404() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupNotFoundEntity(); + + var mockFile = this.mockRepository.Create(); + + // Act + var response = await deviceModelsController.ChangeAvatar(Guid.NewGuid().ToString(), mockFile.Object); + + // Assert + Assert.IsNotNull(response); + Assert.IsAssignableFrom(response.Result); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenGetEntityThrowAnErrorChangeAvatarShouldThrowInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + IFormFile formFile = null; + + SetupErrorEntity(); + + // Act + var act = async () => await deviceModelsController.ChangeAvatar(Guid.NewGuid().ToString(), formFile); + + // Assert + _ = await act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task DeleteAvatarShouldRemoveModelImage() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + var entity = SetupMockEntity(); + + _ = this.mockDeviceModelImageManager.Setup(c => c.DeleteDeviceModelImageAsync( + It.Is(x => x == entity.RowKey))) + .Returns(Task.CompletedTask); + + // Act + var result = await deviceModelsController.DeleteAvatar(entity.RowKey); + + // Assert + Assert.IsNotNull(result); + Assert.IsAssignableFrom(result); + + this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); + this.mockDeviceModelImageManager.VerifyAll(); + } + + [Test] + public async Task WhenModelNotExistsDeleteAvatarShouldReturn404() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupNotFoundEntity(); + + _ = this.mockRepository.Create(); + + // Act + var result = await deviceModelsController.DeleteAvatar(Guid.NewGuid().ToString()); + + // Assert + Assert.IsNotNull(result); + Assert.IsAssignableFrom(result); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenGetEntityThrowAnErrorDeleteAvatarShouldThrowInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupErrorEntity(); + + // Act + var act = async () => await deviceModelsController.DeleteAvatar(Guid.NewGuid().ToString()); + + // Assert + _ = await act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task PostShouldCreateANewEntity() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + SetupNotFoundEntity(); + + var requestModel = new LoRaDeviceModel + { + Name = Guid.NewGuid().ToString(), + ModelId = Guid.NewGuid().ToString() + }; + var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); + + var mockResponse = this.mockRepository.Create(); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( + It.Is(x => x.RowKey == requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(mockResponse.Object); + + _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( + It.Is(x => x.RowKey == requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.IsAny())) + .Returns(new Dictionary()); + + _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( + It.IsAny(), + It.Is(x => x == requestModel.Name), + It.IsAny())) + .ReturnsAsync(mockEnrollmentGroup.Object); + + _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( + It.Is(x => x == requestModel.ModelId), + It.IsAny>())) + .Returns(Task.CompletedTask); + + // Act + var result = await deviceModelsController.Post(requestModel); + + // Assert + Assert.IsNotNull(result); + Assert.IsAssignableFrom(result); + var okObjectResult = result as OkResult; + + Assert.IsNotNull(okObjectResult); + Assert.AreEqual(200, okObjectResult.StatusCode); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenEmptyModelIdPostShouldCreateANewEntity() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + var requestModel = new LoRaDeviceModel + { + ModelId = String.Empty, + Name = Guid.NewGuid().ToString(), + }; + + var mockResponse = this.mockRepository.Create(); + var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( + It.Is(x => x.RowKey != requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(mockResponse.Object); + + _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( + It.Is(x => x.RowKey != requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.IsAny())) + .Returns(new Dictionary()); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( + It.IsAny(), + It.Is(x => x == requestModel.Name), + It.IsAny())) + .ReturnsAsync(mockEnrollmentGroup.Object); + + _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( + It.Is(x => x == requestModel.ModelId), + It.IsAny>())) + .Returns(Task.CompletedTask); + + // Act + var result = await deviceModelsController.Post(requestModel); + + // Assert + Assert.IsNotNull(result); + Assert.IsAssignableFrom(result); + var okObjectResult = result as OkResult; + + Assert.IsNotNull(okObjectResult); + Assert.AreEqual(200, okObjectResult.StatusCode); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenDeviceModelIdExistsPostShouldReturnBadRequest() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + var entity = SetupMockEntity(); + + var deviceModel = new LoRaDeviceModel + { + ModelId = entity.RowKey + }; + + // Act + var result = await deviceModelsController.Post(deviceModel); + // Assert + Assert.IsNotNull(result); + Assert.IsAssignableFrom(result); + } + + [Test] + public async Task WhenGetEntityThrowAnErrorPostShouldThrowInternalServerErrorExceptiont() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupErrorEntity(); + + var deviceModel = new LoRaDeviceModel + { + ModelId = Guid.NewGuid().ToString() + }; + + // Act + var act = async () => await deviceModelsController.Post(deviceModel); + + // Assert + _ = await act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task PutShouldUpdateTheDeviceModel() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + var deviceModel = SetupMockEntity(); + var mockResponse = this.mockRepository.Create(); + + var requestModel = new LoRaDeviceModel + { + Name = Guid.NewGuid().ToString(), + ModelId = deviceModel.RowKey + }; + + var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( + It.Is(x => x.RowKey == deviceModel.RowKey && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(mockResponse.Object); + + _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( + It.Is(x => x.RowKey == deviceModel.RowKey && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.Is(x => x == requestModel))) + .Returns(new Dictionary()); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( + It.IsAny(), + It.Is(x => x == requestModel.Name), + It.IsAny())) + .ReturnsAsync(mockEnrollmentGroup.Object); + + _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( + It.Is(x => x == requestModel.ModelId), + It.IsAny>())) + .Returns(Task.CompletedTask); + + // Act + var result = await deviceModelsController.Put(requestModel); + + // Assert + Assert.IsNotNull(result); + Assert.IsAssignableFrom(result); + var okObjectResult = result as OkResult; + + Assert.IsNotNull(okObjectResult); + Assert.AreEqual(200, okObjectResult.StatusCode); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenDeviceModelIdNotExistsPutShouldReturnBadRequest() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + SetupNotFoundEntity(); + + var deviceModel = new LoRaDeviceModel + { + ModelId = Guid.NewGuid().ToString() + }; + + // Act + var result = await deviceModelsController.Put(deviceModel); + // Assert + Assert.IsNotNull(result); + Assert.IsAssignableFrom(result); + } + + [Test] + public async Task WhenGetEntityThrowAnErrorPutShouldThrowInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + SetupErrorEntity(); + + var deviceModel = new LoRaDeviceModel + { + ModelId = Guid.NewGuid().ToString() + }; + + // Act + var act = async () => await deviceModelsController.Put(deviceModel); + + // Assert + _ = await act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task DeleteShouldRemoveTheEntityCommandsAndAvatar() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + var id = Guid.NewGuid().ToString(); + var commandId = Guid.NewGuid().ToString(); + var returned = false; + + var mockModelResponse = this.mockRepository.Create>(); + + var mockResponse = this.mockRepository.Create(); + var mockTableResponse = this.mockRepository.Create>(); + var mockEnumerator = this.mockRepository.Create>(); + _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); + _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => + { + if (returned) + return false; + + returned = true; + return true; + }); + + _ = mockEnumerator.Setup(x => x.Current) + .Returns(new TableEntity(id, commandId)); + + _ = mockTableResponse.Setup(x => x.GetEnumerator()) + .Returns(mockEnumerator.Object); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( + It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.Is(k => k == id), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(mockModelResponse.Object); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.DeleteEntityAsync( + It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.Is(k => k == id), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(mockResponse.Object); + + _ = this.mockDeviceService.Setup(c => c.GetAllDevice( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(new PaginationResult + { + Items = new List() + }); + + _ = this.mockDeviceModelImageManager.Setup(c => c.DeleteDeviceModelImageAsync(It.Is(x => x == id))) + .Returns(Task.CompletedTask); + + _ = this.mockCommandsTableClient.Setup(c => c.Query( + It.IsAny>>(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .Returns(mockTableResponse.Object); + + _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( + It.Is(p => p == id), + It.Is(k => k == commandId), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(mockResponse.Object); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) + .Returns(this.mockCommandsTableClient.Object); + + // Act + _ = await deviceModelsController.Delete(id); + + // Assert + this.mockRepository.VerifyAll(); + } + + [Test] + public void WhenGetEntityThrowAnErrorDeleteShouldThrowInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + _ = this.mockDeviceService.Setup(c => c.GetAllDevice( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(new PaginationResult + { + Items = new List() + }); + + SetupErrorEntity(); + + // Act + var act = async () => await deviceModelsController.Delete(Guid.NewGuid().ToString()); + + // Assert + _ = act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenQueryThrowAnErrorDeleteShouldThrowInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + var id = Guid.NewGuid().ToString(); + + var mockModelResponse = this.mockRepository.Create>(); + + _ = this.mockDeviceService.Setup(c => c.GetAllDevice( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(new PaginationResult + { + Items = new List() + }); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( + It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.Is(k => k == id), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(mockModelResponse.Object); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) + .Returns(this.mockCommandsTableClient.Object); + + _ = this.mockCommandsTableClient.Setup(c => c.Query( + It.IsAny>>(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .Throws(new RequestFailedException("")); + + // Act + var act = async () => await deviceModelsController.Delete(id); + + // Assert + _ = await act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + [Test] + public async Task WhenDeleteCommandAsyncThrowAnErrorDeleteShouldThrowInternalServerErrorException() + { + // Arrange + var deviceModelsController = CreateDeviceModelsController(); + + var id = Guid.NewGuid().ToString(); + var commandId = Guid.NewGuid().ToString(); + var returned = false; + + var mockModelResponse = this.mockRepository.Create>(); + + var mockTableResponse = this.mockRepository.Create>(); + var mockEnumerator = this.mockRepository.Create>(); + _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); + _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => + { + if (returned) + return false; + + returned = true; + return true; + }); + + _ = mockEnumerator.Setup(x => x.Current) + .Returns(new TableEntity(id, commandId)); + + _ = mockTableResponse.Setup(x => x.GetEnumerator()) + .Returns(mockEnumerator.Object); + + _ = this.mockDeviceService.Setup(c => c.GetAllDevice( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(new PaginationResult + { + Items = new List() + }); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( + It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.Is(k => k == id), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(mockModelResponse.Object); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) + .Returns(this.mockCommandsTableClient.Object); + + _ = this.mockCommandsTableClient.Setup(c => c.Query( + It.IsAny>>(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .Returns(mockTableResponse.Object); + + _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( + It.Is(p => p == id), + It.Is(k => k == commandId), + It.IsAny(), + It.IsAny())) + .ThrowsAsync(new RequestFailedException("")); + + // Act + var act = async () => await deviceModelsController.Delete(id); + + // Assert + _ = await act.Should().ThrowAsync(); + + this.mockRepository.VerifyAll(); + } + + private TableEntity SetupMockEntity() + { + var mockResponse = this.mockRepository.Create>(); + var modelId = Guid.NewGuid().ToString(); + var entity = new TableEntity(LoRaWANDeviceModelsController.DefaultPartitionKey, modelId); + + mockResponse.Setup(c => c.Value) + .Returns(entity) + .Verifiable(); + + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( + It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.Is(k => k == modelId), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(mockResponse.Object); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + return entity; + } + + private void SetupNotFoundEntity() + { + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( + It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .Throws(new RequestFailedException(StatusCodes.Status404NotFound, "Not Found")); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + } + + private void SetupErrorEntity() + { + _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .Throws(new RequestFailedException("")); + + _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) + .Returns(this.mockDeviceTemplatesTableClient.Object); + + _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); + } + } +}