diff --git a/src/ApplicationCore/Exceptions/CatalogImageMissingException.cs b/src/ApplicationCore/Exceptions/CatalogImageMissingException.cs new file mode 100644 index 0000000..a7c1062 --- /dev/null +++ b/src/ApplicationCore/Exceptions/CatalogImageMissingException.cs @@ -0,0 +1,13 @@ +using System; + +namespace ApplicationCore.Exceptions +{ + public class CatalogImageMissingException : Exception + { + public CatalogImageMissingException(string message, + Exception innerException = null) + : base(message, innerException: innerException) + { + } + } +} diff --git a/src/ApplicationCore/Interfaces/IBasketService.cs b/src/ApplicationCore/Interfaces/IBasketService.cs index 1b868a1..a5f25b9 100644 --- a/src/ApplicationCore/Interfaces/IBasketService.cs +++ b/src/ApplicationCore/Interfaces/IBasketService.cs @@ -14,5 +14,4 @@ namespace ApplicationCore.Interfaces { T Parse(IPrincipal principal); } - } diff --git a/src/ApplicationCore/Interfaces/IImageService.cs b/src/ApplicationCore/Interfaces/IImageService.cs new file mode 100644 index 0000000..ae41333 --- /dev/null +++ b/src/ApplicationCore/Interfaces/IImageService.cs @@ -0,0 +1,16 @@ +using ApplicationCore.Entities; +using Microsoft.eShopWeb.ApplicationCore.Entities; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace ApplicationCore.Interfaces +{ + + public interface IImageService + { + byte[] GetImageBytesById(int id); + } + + + +} diff --git a/src/Infrastructure/FileSystem/LocalFileImageService.cs b/src/Infrastructure/FileSystem/LocalFileImageService.cs new file mode 100644 index 0000000..ab876af --- /dev/null +++ b/src/Infrastructure/FileSystem/LocalFileImageService.cs @@ -0,0 +1,22 @@ +using ApplicationCore.Interfaces; +using Microsoft.AspNetCore.Hosting; +using System.IO; + +namespace Infrastructure.FileSystem +{ + public class LocalFileImageService : IImageService + { + private readonly IHostingEnvironment _env; + + public LocalFileImageService(IHostingEnvironment env) + { + _env = env; + } + public byte[] GetImageBytesById(int id) + { + var contentRoot = _env.ContentRootPath + "//Pics"; + var path = Path.Combine(contentRoot, id + ".png"); + return File.ReadAllBytes(path); + } + } +} diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index b377567..c2c8f95 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -14,5 +14,8 @@ + + + \ No newline at end of file diff --git a/src/Web/Controllers/CatalogController.cs b/src/Web/Controllers/CatalogController.cs index 25d50ae..fa7bb18 100644 --- a/src/Web/Controllers/CatalogController.cs +++ b/src/Web/Controllers/CatalogController.cs @@ -5,18 +5,24 @@ using Microsoft.AspNetCore.Mvc; using System; using System.IO; using System.Threading.Tasks; +using ApplicationCore.Interfaces; +using ApplicationCore.Exceptions; namespace Microsoft.eShopWeb.Controllers { public class CatalogController : Controller { private readonly IHostingEnvironment _env; - private readonly ICatalogService _catalogSvc; + private readonly ICatalogService _catalogService; + private readonly IImageService _imageService; - public CatalogController(IHostingEnvironment env, ICatalogService catalogSvc) + public CatalogController(IHostingEnvironment env, + ICatalogService catalogService, + IImageService imageService) { _env = env; - _catalogSvc = catalogSvc; + _catalogService = catalogService; + _imageService = imageService; } @@ -24,13 +30,13 @@ namespace Microsoft.eShopWeb.Controllers public async Task Index(int? BrandFilterApplied, int? TypesFilterApplied, int? page) { var itemsPage = 10; - var catalog = await _catalogSvc.GetCatalogItems(page ?? 0, itemsPage, BrandFilterApplied, TypesFilterApplied); + var catalog = await _catalogService.GetCatalogItems(page ?? 0, itemsPage, BrandFilterApplied, TypesFilterApplied); var vm = new CatalogIndex() { CatalogItems = catalog.Data, - Brands = await _catalogSvc.GetBrands(), - Types = await _catalogSvc.GetTypes(), + Brands = await _catalogService.GetBrands(), + Types = await _catalogService.GetTypes(), BrandFilterApplied = BrandFilterApplied ?? 0, TypesFilterApplied = TypesFilterApplied ?? 0, PaginationInfo = new PaginationInfo() @@ -53,13 +59,18 @@ namespace Microsoft.eShopWeb.Controllers // GET: //pic/{id} public IActionResult GetImage(int id) { - var contentRoot = _env.ContentRootPath + "//Pics"; - var path = Path.Combine(contentRoot, id + ".png"); - Byte[] b = System.IO.File.ReadAllBytes(path); - return File(b, "image/png"); - + byte[] imageBytes; + try + { + imageBytes = _imageService.GetImageBytesById(id); + } + catch (CatalogImageMissingException ex) + { + return NotFound(); + } + return File(imageBytes, "image/png"); } - + public IActionResult Error() { return View(); diff --git a/src/Web/Startup.cs b/src/Web/Startup.cs index 0bf788f..6ec6990 100644 --- a/src/Web/Startup.cs +++ b/src/Web/Startup.cs @@ -11,6 +11,8 @@ using Infrastructure.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using System.Text; using Microsoft.AspNetCore.Http; +using ApplicationCore.Interfaces; +using Infrastructure.FileSystem; namespace Microsoft.eShopWeb { @@ -65,6 +67,7 @@ namespace Microsoft.eShopWeb services.AddScoped(); services.AddScoped(); services.Configure(Configuration); + services.AddSingleton(); services.AddMvc(); _services = services; diff --git a/tests/IntegrationTests/IntegrationTests.csproj b/tests/IntegrationTests/IntegrationTests.csproj index f27ff35..c3a4881 100644 --- a/tests/IntegrationTests/IntegrationTests.csproj +++ b/tests/IntegrationTests/IntegrationTests.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/tests/UnitTests/UnitTests.csproj b/tests/UnitTests/UnitTests.csproj index f032596..18ba44b 100644 --- a/tests/UnitTests/UnitTests.csproj +++ b/tests/UnitTests/UnitTests.csproj @@ -1,13 +1,25 @@ - + netcoreapp1.1 + + + + + + + + + + + + diff --git a/tests/UnitTests/Web/Controllers/CatalogControllerGetImage.cs b/tests/UnitTests/Web/Controllers/CatalogControllerGetImage.cs new file mode 100644 index 0000000..6bcdb4e --- /dev/null +++ b/tests/UnitTests/Web/Controllers/CatalogControllerGetImage.cs @@ -0,0 +1,60 @@ +using ApplicationCore.Exceptions; +using ApplicationCore.Interfaces; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopWeb.Controllers; +using Moq; +using Xunit; + +namespace UnitTests +{ + public class CatalogControllerGetImage + { + private Mock _mockImageService = new Mock(); + private CatalogController _controller; + private int _testImageId = 123; + private byte[] _testBytes = { 0x01, 0x02, 0x03 }; + + public CatalogControllerGetImage() + { + _controller = new CatalogController(null, null, _mockImageService.Object); + } + + [Fact] + public void CallsImageServiceWithId() + { + _mockImageService + .Setup(i => i.GetImageBytesById(_testImageId)) + .Returns(_testBytes) + .Verifiable(); + + _controller.GetImage(_testImageId); + _mockImageService.Verify(); + } + + [Fact] + public void ReturnsFileResultWithBytesGivenSuccess() + { + _mockImageService + .Setup(i => i.GetImageBytesById(_testImageId)) + .Returns(_testBytes); + + var result = _controller.GetImage(_testImageId); + + var fileResult = Assert.IsType(result); + var bytes = Assert.IsType(fileResult.FileContents); + } + + [Fact] + public void ReturnsNotFoundResultGivenImageMissingException() + { + _mockImageService + .Setup(i => i.GetImageBytesById(_testImageId)) + .Throws(new CatalogImageMissingException("missing image")); + + var result = _controller.GetImage(_testImageId); + + var actionResult = Assert.IsType(result); + } + } +}