Merge pull request #6 from dotnet-architecture/ardalis/tests

Adding unit tests
This commit is contained in:
Steve Smith
2017-04-30 08:27:20 -04:00
committed by GitHub
13 changed files with 241 additions and 21 deletions

View File

@@ -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)
{
}
}
}

View File

@@ -0,0 +1,7 @@
namespace ApplicationCore.Interfaces
{
public interface IAppLogger<T>
{
void LogWarning(string message, params object[] args);
}
}

View File

@@ -14,5 +14,4 @@ namespace ApplicationCore.Interfaces
{ {
T Parse(IPrincipal principal); T Parse(IPrincipal principal);
} }
} }

View File

@@ -0,0 +1,7 @@
namespace ApplicationCore.Interfaces
{
public interface IImageService
{
byte[] GetImageBytesById(int id);
}
}

View 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);
}
}
}
}

View File

@@ -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>

View 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);
}
}
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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>

View File

@@ -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()
}
}
}

View File

@@ -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>

View 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();
}
}
}