This commit is contained in:
Thibaud Gasser 2020-09-20 23:40:36 +02:00
parent 50ffd34e07
commit 5568257499
11 changed files with 134 additions and 49 deletions

View File

@ -1,6 +1,6 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# #
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VegetableShop.Domain", "VegetableShop.Domain\VegetableShop.Domain.csproj", "{9EE77ACA-9351-46CF-B55B-CE76EFBCDB04}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VegetableShop.Domain", "VegetableShop.Domain\VegetableShop.Domain.csproj", "{9EE77ACA-9351-46CF-B55B-CE76EFBCDB04}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VegetableShop.API.IntegrationTests", "VegetableShop.API.IntegrationTests\VegetableShop.API.IntegrationTests.csproj", "{7D802ED7-C73C-437B-A91E-BA013939AF7C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VegetableShop.API.IntegrationTests", "VegetableShop.API.IntegrationTests\VegetableShop.API.IntegrationTests.csproj", "{7D802ED7-C73C-437B-A91E-BA013939AF7C}"
@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VegetableShop.API", "Vegeta
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VegetableShop.Domain.AcceptanceTests", "VegetableShop.Domain.AcceptanceTests\VegetableShop.Domain.AcceptanceTests.csproj", "{BADB4EB0-3817-4114-B256-8162B76C86A3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VegetableShop.Domain.AcceptanceTests", "VegetableShop.Domain.AcceptanceTests\VegetableShop.Domain.AcceptanceTests.csproj", "{BADB4EB0-3817-4114-B256-8162B76C86A3}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_tests", "_tests", "{54A647A6-A4DA-450B-9C0F-4A4912D5B229}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -42,4 +44,8 @@ Global
{BADB4EB0-3817-4114-B256-8162B76C86A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {BADB4EB0-3817-4114-B256-8162B76C86A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BADB4EB0-3817-4114-B256-8162B76C86A3}.Release|Any CPU.Build.0 = Release|Any CPU {BADB4EB0-3817-4114-B256-8162B76C86A3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{BADB4EB0-3817-4114-B256-8162B76C86A3} = {54A647A6-A4DA-450B-9C0F-4A4912D5B229}
{7D802ED7-C73C-437B-A91E-BA013939AF7C} = {54A647A6-A4DA-450B-9C0F-4A4912D5B229}
EndGlobalSection
EndGlobal EndGlobal

View File

@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using VegetableShop.API.Services; using VegetableShop.API.Services;
using VegetableShop.Domain.Model;
using VegetableShop.Infrastructure.Persistence; using VegetableShop.Infrastructure.Persistence;
using Xunit; using Xunit;
@ -8,18 +9,28 @@ namespace VegetableShop.API.IntegrationTests
public class ConsumersServicesTests public class ConsumersServicesTests
{ {
private readonly ConsumerServices _consumerServices; private readonly ConsumerServices _consumerServices;
private readonly ConsumerRepositoryImpl _consumerRepository;
private readonly FarmerRepositoryImpl _farmerRepository;
private readonly VegetableRepositoryImpl _vegetableRepository;
private readonly Context _context;
public ConsumersServicesTests() public ConsumersServicesTests()
{ {
var loggerFactory = new NullLoggerFactory(); var loggerFactory = new NullLoggerFactory();
var consumerRepository = new ConsumerRepositoryImpl(loggerFactory); _context = new Context(loggerFactory);
var farmerRepository = new FarmerRepositoryImpl(loggerFactory); _consumerRepository = new ConsumerRepositoryImpl(_context);
var vegetableRepositoryImpl = new VegetableRepositoryImpl(); _farmerRepository = new FarmerRepositoryImpl(_context);
_vegetableRepository = new VegetableRepositoryImpl(_context);
_consumerServices = new ConsumerServices(loggerFactory, _consumerServices = new ConsumerServices(loggerFactory,
consumerRepository, _consumerRepository,
farmerRepository, _farmerRepository,
vegetableRepositoryImpl); _vegetableRepository);
// Initialize test data
_context.Consumers.Add(1L, new Consumer(loggerFactory));
_context.Farmers.Add(1L, new Farmer(loggerFactory));
_context.Vegetables.Add(1L, new Vegetable("carrot"));
} }
[Fact] [Fact]

View File

@ -14,8 +14,9 @@ namespace VegetableShop.API.IntegrationTests
public FarmerServicesTests() public FarmerServicesTests()
{ {
var loggerFactory = new NullLoggerFactory(); var loggerFactory = new NullLoggerFactory();
var vegetableRepository = new VegetableRepositoryImpl(); var context = new Context(loggerFactory);
_farmerRepository = new FarmerRepositoryImpl(loggerFactory); var vegetableRepository = new VegetableRepositoryImpl(context);
_farmerRepository = new FarmerRepositoryImpl(context);
_farmerServices = new FarmerServices(loggerFactory, _farmerRepository, vegetableRepository); _farmerServices = new FarmerServices(loggerFactory, _farmerRepository, vegetableRepository);
} }

View File

@ -32,21 +32,22 @@ namespace VegetableShop.API
private Program() private Program()
{ {
var loggerFactory = SetupLogging(); var loggerFactory = SetupLogging();
var context = new Context(loggerFactory);
ConsumerRepository consumerRepository = new ConsumerRepositoryImpl(loggerFactory); ConsumerRepository consumerRepository = new ConsumerRepositoryImpl(context);
FarmerRepository farmerRepository = new FarmerRepositoryImpl(loggerFactory); FarmerRepository farmerRepository = new FarmerRepositoryImpl(context);
VegetableRepository vegetableRepository = new VegetableRepositoryImpl(); VegetableRepository vegetableRepository = new VegetableRepositoryImpl(context);
_consumerServices = new ConsumerServices(loggerFactory, _consumerServices = new ConsumerServices(loggerFactory,
consumerRepository, consumerRepository,
farmerRepository,
vegetableRepository);
_farmerServices = new FarmerServices(loggerFactory,
farmerRepository, farmerRepository,
vegetableRepository); vegetableRepository);
DomainEvents.AddObserver(new LogItemOnFarmerPutOnSaleEvent(_loggerFactory)); _farmerServices = new FarmerServices(loggerFactory,
farmerRepository,
vegetableRepository);
DomainEvents.AddObserver(new LogItemOnFarmerPutOnSaleEvent(loggerFactory));
} }
private void Run() private void Run()
@ -56,7 +57,7 @@ namespace VegetableShop.API
_consumerServices.BuyVegetables(1, 1, 1, 10); _consumerServices.BuyVegetables(1, 1, 1, 10);
} }
public static void Main(string[] args) public static void Main()
{ {
new Program().Run(); new Program().Run();
} }

View File

@ -0,0 +1,31 @@
using FakeItEasy;
using Microsoft.Extensions.Logging;
using VegetableShop.Domain.Events;
using VegetableShop.Domain.Model;
using Xunit;
namespace VegetableShop.Domain.UnitTests
{
public class LogItemOnFarmerPutOnSaleEventTest
{
private readonly LogItemOnFarmerPutOnSaleEvent _handler;
private readonly ILogger<LogItemOnFarmerPutOnSaleEvent> _logger;
public LogItemOnFarmerPutOnSaleEventTest()
{
_logger = A.Fake<ILogger<LogItemOnFarmerPutOnSaleEvent>>();
_handler = new LogItemOnFarmerPutOnSaleEvent(_logger);
}
[Fact]
public void Test1()
{
var evt = new FarmerPutOnSaleEvent(1L, A.Fake<Vegetable>(), new Price());
_handler.Handle(evt);
A.CallTo(() => _logger.LogInformation(default))
.WithAnyArguments()
.MustHaveHappenedOnceExactly();
}
}
}

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FakeItEasy" Version="6.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VegetableShop.Domain\VegetableShop.Domain.csproj" />
</ItemGroup>
</Project>

View File

@ -5,9 +5,9 @@ namespace VegetableShop.Domain.Errors
{ {
public class UnauthorizedSaleException : Exception public class UnauthorizedSaleException : Exception
{ {
public UnauthorizedSaleException(Farmer farmer, Vegetable vegetable) public UnauthorizedSaleException(Farmer farmer, Vegetable vegetable) :
base($"Unauthorized sale of {vegetable} for {farmer}")
{ {
throw new NotImplementedException();
} }
} }
} }

View File

@ -1,22 +1,17 @@
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using VegetableShop.Domain.Model; using VegetableShop.Domain.Model;
using VegetableShop.Domain.Repositories; using VegetableShop.Domain.Repositories;
namespace VegetableShop.Infrastructure.Persistence namespace VegetableShop.Infrastructure.Persistence
{ {
public class ConsumerRepositoryImpl: ConsumerRepository public class ConsumerRepositoryImpl : ConsumerRepository
{ {
private readonly Dictionary<long, Consumer> _consumers; private readonly Context _context;
public ConsumerRepositoryImpl(ILoggerFactory loggerFactory) public ConsumerRepositoryImpl(Context context)
{ {
_consumers = new Dictionary<long, Consumer> _context = context;
{
{ 1L, new Consumer(loggerFactory) }
};
} }
public Consumer GetById(in long consumerId) => _consumers[consumerId]; public Consumer GetById(in long consumerId) => _context.Consumers[consumerId];
} }
} }

View File

@ -0,0 +1,26 @@
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using VegetableShop.Domain.Model;
namespace VegetableShop.Infrastructure.Persistence
{
public class Context
{
public Dictionary<long, Consumer> Consumers { get; }
public Dictionary<long, Farmer> Farmers { get; }
public Dictionary<long, Vegetable> Vegetables { get; }
public Context(ILoggerFactory loggerFactory)
{
Consumers = new Dictionary<long, Consumer> {
{ 1L, new Consumer(loggerFactory) }
};
Farmers = new Dictionary<long, Farmer> {
{ 1L, new Farmer(loggerFactory) }
};
Vegetables = new Dictionary<long, Vegetable> {
{ 1L, new Vegetable("carrot") }
};;
}
}
}

View File

@ -1,5 +1,3 @@
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using VegetableShop.Domain.Model; using VegetableShop.Domain.Model;
using VegetableShop.Domain.Repositories; using VegetableShop.Domain.Repositories;
@ -7,19 +5,12 @@ namespace VegetableShop.Infrastructure.Persistence
{ {
public class FarmerRepositoryImpl: FarmerRepository public class FarmerRepositoryImpl: FarmerRepository
{ {
private readonly ILoggerFactory _loggerFactory; private readonly Context _context;
public FarmerRepositoryImpl(ILoggerFactory loggerFactory) public FarmerRepositoryImpl(Context context)
{ {
_loggerFactory = loggerFactory; _context = context;
_farmers = new Dictionary<long, Farmer>
{
{ 1L, new Farmer(_loggerFactory) }
};
} }
public Farmer GetById(in long farmerId) => _context.Farmers[farmerId];
private readonly Dictionary<long, Farmer> _farmers;
public Farmer GetById(in long farmerId) => _farmers[farmerId];
} }
} }

View File

@ -1,4 +1,3 @@
using System.Collections.Generic;
using VegetableShop.Domain.Model; using VegetableShop.Domain.Model;
using VegetableShop.Domain.Repositories; using VegetableShop.Domain.Repositories;
@ -6,10 +5,13 @@ namespace VegetableShop.Infrastructure.Persistence
{ {
public class VegetableRepositoryImpl: VegetableRepository public class VegetableRepositoryImpl: VegetableRepository
{ {
private readonly Dictionary<long, Vegetable> _vegetables = new Dictionary<long, Vegetable> private readonly Context _context;
public VegetableRepositoryImpl(Context context)
{ {
{ 1L, new Vegetable("carrot") } _context = context;
}; }
public Vegetable GetById(in long vegetableId) => _vegetables[vegetableId];
public Vegetable GetById(in long vegetableId) => _context.Vegetables[vegetableId];
} }
} }