Skip to content

Commit

Permalink
Added Test examples and code complexity
Browse files Browse the repository at this point in the history
  • Loading branch information
leosperry committed Nov 23, 2020
1 parent 5dd62cd commit 4392896
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 1 deletion.
72 changes: 72 additions & 0 deletions SampleTests/OrderLogicTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Moq;
using Samples.BlanketsHoldingNoHeat;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace SampleTests
{
public class OrderLogicTests
{
[Fact]
public async Task WhenValidationErrorsExist_ReturnsErrorsAndDoesNotSave()
{
//arrange
Mock<IOrderValidator> mockValidator = new Mock<IOrderValidator>();
Mock<IOrderProvider> mockProvider = new Mock<IOrderProvider>();
Mock<ILogger> mockLogger = new Mock<ILogger>();

mockValidator.Setup(v => v.ValidateOrder(It.IsAny<Order>()))
.ReturnsAsync(new OrderValidationError[] {
new OrderValidationError()
{
Message = "Live long and prosper"
}
});
var logicUnderTest = new OrderLogic(
mockValidator.Object,
mockProvider.Object,
mockLogger.Object);

//act
var result = await logicUnderTest.PlaceOrder(new Order());

//assert
mockLogger.Verify(l => l.Log(It.IsAny<string>()));
Assert.Single(result);
var error = result.First();
Assert.Equal("Live long and prosper", error.Message);

mockProvider.Verify(p => p.SaveOrder(It.IsAny<Order>()), Times.Never);
}

[Fact]
public async Task WhenNoValidationErrors_SavesOrder()
{
//arrange
Mock<IOrderValidator> mockValidator = new Mock<IOrderValidator>();
Mock<IOrderProvider> mockProvider = new Mock<IOrderProvider>();
Mock<ILogger> mockLogger = new Mock<ILogger>();

mockValidator.Setup(v => v.ValidateOrder(It.IsAny<Order>()))
.ReturnsAsync(Enumerable.Empty<OrderValidationError>());

var fakeOrder = new Order();

var logicUnderTest = new OrderLogic(
mockValidator.Object,
mockProvider.Object,
mockLogger.Object);

//act
var result = await logicUnderTest.PlaceOrder(fakeOrder);

//assert
Assert.Empty(result);
mockProvider.Verify(p => p.SaveOrder(fakeOrder), Times.Once);
}
}
}
20 changes: 20 additions & 0 deletions SampleTests/SampleTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Samples\Samples.csproj" />
</ItemGroup>

</Project>
34 changes: 34 additions & 0 deletions Samples/BlanketsHoldingNoHeat/Interfaces.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Samples.BlanketsHoldingNoHeat
{
public interface IOrderLogic
{
Task<IEnumerable<OrderValidationError>> PlaceOrder(Order order);
}

public interface IOrderValidator
{
Task<IEnumerable<OrderValidationError>> ValidateOrder(Order order);
}

public class OrderValidationError
{
public string Message { get; set; }
}

public interface ILogger
{
void Log(string message);
}

public interface IOrderProvider
{
Task SaveOrder(Order order);
}

}

10 changes: 10 additions & 0 deletions Samples/BlanketsHoldingNoHeat/Order.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Samples.BlanketsHoldingNoHeat
{
public class Order
{
}
}
35 changes: 35 additions & 0 deletions Samples/BlanketsHoldingNoHeat/OrderLogic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Samples.BlanketsHoldingNoHeat
{
public class OrderLogic : IOrderLogic
{
readonly IOrderValidator _validator;
readonly IOrderProvider _orderProvider;
readonly ILogger _logger;

public OrderLogic(IOrderValidator validator, IOrderProvider orderProvider, ILogger logger)
{
_validator = validator;
_orderProvider = orderProvider;
_logger = logger;
}

public async Task<IEnumerable<OrderValidationError>> PlaceOrder(Order order)
{
var errors = await _validator.ValidateOrder(order);

if (errors.Any())
{
_logger.Log("Cannot process order");
return errors;
}

await _orderProvider.SaveOrder(order);

return errors;
}
}
}
46 changes: 46 additions & 0 deletions Samples/BlanketsHoldingNoHeat/OrderLogic/PlaceOrderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//using Moq;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
//using Xunit;

//namespace Samples.BlanketsHoldingNoHeat.OrderLogicTests
//{

// public class PlaceOrderTests
// {
// [Fact]
// public async Task WhenValidationErrorsExist_ReturnsErrorsAndDoesNotSave()
// {
// //arrange
// Mock<IOrderValidator> mockValidator = new Mock<IOrderValidator>();
// Mock<IOrderProvider> mockProvider = new Mock<IOrderProvider>();
// Mock<ILogger> mockLogger = new Mock<ILogger>();

// mockValidator.Setup(v => v.ValidateOrder(It.IsAny<Order>()))
// .ReturnsAsync(new OrderValidationError[] {
// new OrderValidationError()
// {
// Message = "Live long and prosper"
// }
// });
// var logicUnderTest = new OrderLogic(
// mockValidator.Object,
// mockProvider.Object,
// mockLogger.Object);

// //act
// var result = await logicUnderTest.PlaceOrder(new Order());

// //assert
// mockLogger.Verify(l => l.Log(It.IsAny<string>()));
// Assert.Single(result);
// var error = result.First();
// Assert.Equal("Live long and prosper", error.Message);

// mockProvider.Verify(p => p.SaveOrder(It.IsAny<Order>()), Times.Never);
// }
// }
//}
104 changes: 104 additions & 0 deletions Samples/OofOne/Examples.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Samples.OofOne
{
class Examples
{
readonly ICategoryProvider _categoryProvider;
readonly IBookProvider _bookProvider;

IEnumerable<Category> GetCategoriesFromBooks(
IEnumerable<Book> books,
IEnumerable<Category> categories)
{
List<Category> usedCategories = new List<Category>();

foreach (var book in books)
{
foreach (var catId in book.CategoryIds)
{
var category = categories.FirstOrDefault(c => c.ID == catId);
if (category != null &&
usedCategories.Any(uc => uc.ID == category.ID))
{
usedCategories.Add(category);
}
}
}
return usedCategories;
}

IEnumerable<Category> GetCategoriesFromBooks2(
IEnumerable<Book> books,
IEnumerable<Category> categories)
{
var usedCategoryIds = books.SelectMany(b => b.CategoryIds);
var categoryHash = new HashSet<int>(usedCategoryIds);

foreach (var category in categories)
{
if (categoryHash.Contains(category.ID))
{
yield return category;
}
}
}

public IEnumerable<Book> GetRelatedBooks(Book book)
{
Dictionary<Book, int> bookCounts = new Dictionary<Book, int>();
foreach (var cat in _categoryProvider.GetCategories(book))
{
var categories = _bookProvider.GetBooksInCategory(cat.ID);
UpdateBookCounts(bookCounts, categories);
}

return bookCounts.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key);
}

private static void UpdateBookCounts(
Dictionary<Book, int> bookCounts, IEnumerable<Book> books)
{
foreach (var relatedBook in books)
{
if (bookCounts.ContainsKey(relatedBook))
{
bookCounts[relatedBook] = bookCounts[relatedBook] + 1;
}
else
{
bookCounts[relatedBook] = 1;
}
}
}
}


public interface ICategoryProvider
{
IEnumerable<Category> GetCategories(Book book);
}

public interface IBookProvider
{
Book GetById(int id);
IEnumerable<Book> GetBooksInCategory(int catId);
}

public class Book
{
public int ID { get; set; }
public string Title { get; set; }
public IEnumerable<int> CategoryIds { get; set; }
}

public class Category
{
public int ID { get; set; }
public string Name { get; set; }

}
}
9 changes: 9 additions & 0 deletions Samples/Samples.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,13 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Moq" Version="4.15.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
8 changes: 7 additions & 1 deletion TaoOfCode.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ VisualStudioVersion = 16.0.30711.63
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples", "Samples\Samples.csproj", "{F4CC7DE2-E690-470F-B697-DE1B2CBA0187}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsvProcessor", "CsvProcessor\CsvProcessor.csproj", "{763A0AEC-9975-462C-939A-9F106718B678}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CsvProcessor", "CsvProcessor\CsvProcessor.csproj", "{763A0AEC-9975-462C-939A-9F106718B678}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleTests", "SampleTests\SampleTests.csproj", "{998DA7AB-6D21-4D71-91CA-906A7DD4CE4D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -21,6 +23,10 @@ Global
{763A0AEC-9975-462C-939A-9F106718B678}.Debug|Any CPU.Build.0 = Debug|Any CPU
{763A0AEC-9975-462C-939A-9F106718B678}.Release|Any CPU.ActiveCfg = Release|Any CPU
{763A0AEC-9975-462C-939A-9F106718B678}.Release|Any CPU.Build.0 = Release|Any CPU
{998DA7AB-6D21-4D71-91CA-906A7DD4CE4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{998DA7AB-6D21-4D71-91CA-906A7DD4CE4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{998DA7AB-6D21-4D71-91CA-906A7DD4CE4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{998DA7AB-6D21-4D71-91CA-906A7DD4CE4D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down

0 comments on commit 4392896

Please sign in to comment.