Merge pull request #6 from dotnet-architecture/ardalis/tests
Adding unit tests
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ApplicationCore.Exceptions
|
||||||
|
{
|
||||||
|
public class CatalogImageMissingException : Exception
|
||||||
|
{
|
||||||
|
public CatalogImageMissingException(string message,
|
||||||
|
Exception innerException = null)
|
||||||
|
: base(message, innerException: innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public CatalogImageMissingException(Exception innerException)
|
||||||
|
: base("No catalog image found for the provided id.",
|
||||||
|
innerException: innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/ApplicationCore/Interfaces/IAppLogger.cs
Normal file
7
src/ApplicationCore/Interfaces/IAppLogger.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ApplicationCore.Interfaces
|
||||||
|
{
|
||||||
|
public interface IAppLogger<T>
|
||||||
|
{
|
||||||
|
void LogWarning(string message, params object[] args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,5 +14,4 @@ namespace ApplicationCore.Interfaces
|
|||||||
{
|
{
|
||||||
T Parse(IPrincipal principal);
|
T Parse(IPrincipal principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
7
src/ApplicationCore/Interfaces/IImageService.cs
Normal file
7
src/ApplicationCore/Interfaces/IImageService.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ApplicationCore.Interfaces
|
||||||
|
{
|
||||||
|
public interface IImageService
|
||||||
|
{
|
||||||
|
byte[] GetImageBytesById(int id);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/Infrastructure/FileSystem/LocalFileImageService.cs
Normal file
30
src/Infrastructure/FileSystem/LocalFileImageService.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using ApplicationCore.Exceptions;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var contentRoot = _env.ContentRootPath + "//Pics";
|
||||||
|
var path = Path.Combine(contentRoot, id + ".png");
|
||||||
|
return File.ReadAllBytes(path);
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException ex)
|
||||||
|
{
|
||||||
|
throw new CatalogImageMissingException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,5 +14,8 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.0.2" />
|
||||||
<PackageReference Include="StructureMap.Microsoft.DependencyInjection" Version="1.3.0" />
|
<PackageReference Include="StructureMap.Microsoft.DependencyInjection" Version="1.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ApplicationCore\ApplicationCore.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
18
src/Infrastructure/Logging/LoggerAdapter.cs
Normal file
18
src/Infrastructure/Logging/LoggerAdapter.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using ApplicationCore.Interfaces;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Infrastructure.Logging
|
||||||
|
{
|
||||||
|
public class LoggerAdapter<T> : IAppLogger<T>
|
||||||
|
{
|
||||||
|
private readonly ILogger<T> _logger;
|
||||||
|
public LoggerAdapter(ILoggerFactory loggerFactory)
|
||||||
|
{
|
||||||
|
_logger = loggerFactory.CreateLogger<T>();
|
||||||
|
}
|
||||||
|
public void LogWarning(string message, params object[] args)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(message, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,34 +3,42 @@ using Microsoft.eShopWeb.ViewModels;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using ApplicationCore.Interfaces;
|
||||||
|
using ApplicationCore.Exceptions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.Controllers
|
namespace Microsoft.eShopWeb.Controllers
|
||||||
{
|
{
|
||||||
public class CatalogController : Controller
|
public class CatalogController : Controller
|
||||||
{
|
{
|
||||||
private readonly IHostingEnvironment _env;
|
private readonly IHostingEnvironment _env;
|
||||||
private readonly ICatalogService _catalogSvc;
|
private readonly ICatalogService _catalogService;
|
||||||
|
private readonly IImageService _imageService;
|
||||||
|
private readonly IAppLogger<CatalogController> _logger;
|
||||||
|
|
||||||
public CatalogController(IHostingEnvironment env, ICatalogService catalogSvc)
|
public CatalogController(IHostingEnvironment env,
|
||||||
|
ICatalogService catalogService,
|
||||||
|
IImageService imageService,
|
||||||
|
IAppLogger<CatalogController> logger)
|
||||||
{
|
{
|
||||||
_env = env;
|
_env = env;
|
||||||
_catalogSvc = catalogSvc;
|
_catalogService = catalogService;
|
||||||
|
_imageService = imageService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GET: /<controller>/
|
// GET: /<controller>/
|
||||||
public async Task<IActionResult> Index(int? BrandFilterApplied, int? TypesFilterApplied, int? page)
|
public async Task<IActionResult> Index(int? BrandFilterApplied, int? TypesFilterApplied, int? page)
|
||||||
{
|
{
|
||||||
var itemsPage = 10;
|
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()
|
var vm = new CatalogIndex()
|
||||||
{
|
{
|
||||||
CatalogItems = catalog.Data,
|
CatalogItems = catalog.Data,
|
||||||
Brands = await _catalogSvc.GetBrands(),
|
Brands = await _catalogService.GetBrands(),
|
||||||
Types = await _catalogSvc.GetTypes(),
|
Types = await _catalogService.GetTypes(),
|
||||||
BrandFilterApplied = BrandFilterApplied ?? 0,
|
BrandFilterApplied = BrandFilterApplied ?? 0,
|
||||||
TypesFilterApplied = TypesFilterApplied ?? 0,
|
TypesFilterApplied = TypesFilterApplied ?? 0,
|
||||||
PaginationInfo = new PaginationInfo()
|
PaginationInfo = new PaginationInfo()
|
||||||
@@ -48,18 +56,23 @@ namespace Microsoft.eShopWeb.Controllers
|
|||||||
return View(vm);
|
return View(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("[controller]/pic/{id}")]
|
||||||
[Route("[controller]/pic/{id}")]
|
|
||||||
// GET: /<controller>/pic/{id}
|
|
||||||
public IActionResult GetImage(int id)
|
public IActionResult GetImage(int id)
|
||||||
{
|
{
|
||||||
var contentRoot = _env.ContentRootPath + "//Pics";
|
byte[] imageBytes;
|
||||||
var path = Path.Combine(contentRoot, id + ".png");
|
try
|
||||||
Byte[] b = System.IO.File.ReadAllBytes(path);
|
{
|
||||||
return File(b, "image/png");
|
imageBytes = _imageService.GetImageBytesById(id);
|
||||||
|
}
|
||||||
|
catch (CatalogImageMissingException ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"No image found for id: {id}");
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
return File(imageBytes, "image/png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IActionResult Error()
|
public IActionResult Error()
|
||||||
{
|
{
|
||||||
return View();
|
return View();
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ using Infrastructure.Identity;
|
|||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using ApplicationCore.Interfaces;
|
||||||
|
using Infrastructure.FileSystem;
|
||||||
|
using Infrastructure.Logging;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb
|
namespace Microsoft.eShopWeb
|
||||||
{
|
{
|
||||||
@@ -65,6 +68,8 @@ namespace Microsoft.eShopWeb
|
|||||||
services.AddScoped<ICatalogService, CachedCatalogService>();
|
services.AddScoped<ICatalogService, CachedCatalogService>();
|
||||||
services.AddScoped<CatalogService>();
|
services.AddScoped<CatalogService>();
|
||||||
services.Configure<CatalogSettings>(Configuration);
|
services.Configure<CatalogSettings>(Configuration);
|
||||||
|
services.AddSingleton<IImageService, LocalFileImageService>();
|
||||||
|
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
|
||||||
_services = services;
|
_services = services;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
@@ -10,4 +10,12 @@
|
|||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Web\Web.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Microsoft.eShopWeb.Controllers;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace IntegrationTests.Web.Controllers
|
||||||
|
{
|
||||||
|
public class CatalogControllerGetImage
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void ReturnsFileContentResultGivenValidId()
|
||||||
|
{
|
||||||
|
//var controller = new CatalogController()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,25 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.0" />
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
|
||||||
|
<PackageReference Include="Moq" Version="4.7.8" />
|
||||||
<PackageReference Include="xunit" Version="2.2.0" />
|
<PackageReference Include="xunit" Version="2.2.0" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Web\Web.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
83
tests/UnitTests/Web/Controllers/CatalogControllerGetImage.cs
Normal file
83
tests/UnitTests/Web/Controllers/CatalogControllerGetImage.cs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
using ApplicationCore.Exceptions;
|
||||||
|
using ApplicationCore.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.eShopWeb.Controllers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace UnitTests
|
||||||
|
{
|
||||||
|
public class CatalogControllerGetImage
|
||||||
|
{
|
||||||
|
private Mock<IImageService> _mockImageService = new Mock<IImageService>();
|
||||||
|
private Mock<IAppLogger<CatalogController>> _mockLogger = new Mock<IAppLogger<CatalogController>>();
|
||||||
|
private CatalogController _controller;
|
||||||
|
private int _testImageId = 123;
|
||||||
|
private byte[] _testBytes = { 0x01, 0x02, 0x03 };
|
||||||
|
|
||||||
|
public CatalogControllerGetImage()
|
||||||
|
{
|
||||||
|
_controller = new CatalogController(null, null, _mockImageService.Object,
|
||||||
|
_mockLogger.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CallsImageServiceWithId()
|
||||||
|
{
|
||||||
|
SetupImageWithTestBytes();
|
||||||
|
|
||||||
|
_controller.GetImage(_testImageId);
|
||||||
|
_mockImageService.Verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReturnsFileResultWithBytesGivenSuccess()
|
||||||
|
{
|
||||||
|
SetupImageWithTestBytes();
|
||||||
|
|
||||||
|
var result = _controller.GetImage(_testImageId);
|
||||||
|
|
||||||
|
var fileResult = Assert.IsType<FileContentResult>(result);
|
||||||
|
var bytes = Assert.IsType<byte[]>(fileResult.FileContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReturnsNotFoundResultGivenImageMissingException()
|
||||||
|
{
|
||||||
|
SetupMissingImage();
|
||||||
|
|
||||||
|
var result = _controller.GetImage(_testImageId);
|
||||||
|
|
||||||
|
var actionResult = Assert.IsType<NotFoundResult>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LogsWarningGivenImageMissingException()
|
||||||
|
{
|
||||||
|
SetupMissingImage();
|
||||||
|
_mockLogger.Setup(l => l.LogWarning(It.IsAny<string>()))
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
_controller.GetImage(_testImageId);
|
||||||
|
|
||||||
|
_mockLogger.Verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupMissingImage()
|
||||||
|
{
|
||||||
|
_mockImageService
|
||||||
|
.Setup(i => i.GetImageBytesById(_testImageId))
|
||||||
|
.Throws(new CatalogImageMissingException("missing image"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupImageWithTestBytes()
|
||||||
|
{
|
||||||
|
_mockImageService
|
||||||
|
.Setup(i => i.GetImageBytesById(_testImageId))
|
||||||
|
.Returns(_testBytes)
|
||||||
|
.Verifiable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user