From 47524b88598a49da9666fc942764721cc7393005 Mon Sep 17 00:00:00 2001
From: kentah <158997636+KentaHizume@users.noreply.github.com>
Date: Tue, 27 Feb 2024 10:28:31 +0900
Subject: [PATCH 01/17] =?UTF-8?q?Order=E3=80=81ConsoleAppHostedService?=
=?UTF-8?q?=E3=81=A7TimeProvider=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=99?=
=?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../solution/Directory.Packages.props | 1 +
.../ConsoleAppHostedService.cs | 16 ++---
.../ServiceCollectionExtensions.cs | 1 +
.../Hosting/ConsoleAppHostedServiceTest.cs | 60 +++++++++++++++----
.../ServiceCollectionExtensionsTest.cs | 4 ++
.../Maris.ConsoleApp.UnitTests.csproj | 1 +
.../dressca-backend/Directory.Packages.props | 1 +
.../Dressca.ApplicationCore/Ordering/Order.cs | 49 ++++++++++++++-
.../ApplicationCore/Ordering/OrderTest.cs | 19 ++++++
.../Dressca.UnitTests.csproj | 1 +
10 files changed, 132 insertions(+), 21 deletions(-)
diff --git a/samples/ConsoleAppWithDI/solution/Directory.Packages.props b/samples/ConsoleAppWithDI/solution/Directory.Packages.props
index e7c688141..bd2506300 100644
--- a/samples/ConsoleAppWithDI/solution/Directory.Packages.props
+++ b/samples/ConsoleAppWithDI/solution/Directory.Packages.props
@@ -7,6 +7,7 @@
+
diff --git a/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ConsoleAppHostedService.cs b/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ConsoleAppHostedService.cs
index 83391d016..40a42a06d 100644
--- a/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ConsoleAppHostedService.cs
+++ b/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ConsoleAppHostedService.cs
@@ -1,5 +1,4 @@
-using System.Diagnostics;
-using Maris.ConsoleApp.Core;
+using Maris.ConsoleApp.Core;
using Maris.ConsoleApp.Hosting.Resources;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@@ -15,7 +14,8 @@ internal class ConsoleAppHostedService : IHostedService
private readonly ConsoleAppSettings settings;
private readonly CommandExecutor executor;
private readonly ILogger logger;
- private readonly Stopwatch stopwatch = new();
+ private readonly TimeProvider timeProvider;
+ private long startTime;
///
/// クラスの新しいインスタンスを初期化します。
@@ -24,20 +24,23 @@ internal class ConsoleAppHostedService : IHostedService
/// コンソールアプリケーションの設定項目を管理するオブジェクト。
/// コマンドの実行を管理するオブジェクト。
/// ロガー
+ /// 日時のプロバイダ。
///
///
/// - が です。
/// - が です。
/// - が です。
/// - が です。
+ /// - が です。
///
///
- public ConsoleAppHostedService(IHostApplicationLifetime lifetime, ConsoleAppSettings settings, CommandExecutor executor, ILogger logger)
+ public ConsoleAppHostedService(IHostApplicationLifetime lifetime, ConsoleAppSettings settings, CommandExecutor executor, ILogger logger, TimeProvider timeProvider)
{
this.lifetime = lifetime ?? throw new ArgumentNullException(nameof(lifetime));
this.settings = settings ?? throw new ArgumentNullException(nameof(settings));
this.executor = executor ?? throw new ArgumentNullException(nameof(executor));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ this.timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
}
///
@@ -54,7 +57,7 @@ public ConsoleAppHostedService(IHostApplicationLifetime lifetime, ConsoleAppSett
/// タスク。
public async Task StartAsync(CancellationToken cancellationToken)
{
- this.stopwatch.Start();
+ this.startTime = this.timeProvider.GetTimestamp();
this.logger.LogInformation(Events.StartHostingService, Messages.StartHostingService, this.executor.CommandName);
try
{
@@ -85,13 +88,12 @@ public async Task StartAsync(CancellationToken cancellationToken)
/// タスク。
public Task StopAsync(CancellationToken cancellationToken)
{
- this.stopwatch.Stop();
this.logger.LogInformation(
Events.StopHostingService,
Messages.StopHostingService,
this.executor.CommandName,
Environment.ExitCode,
- this.stopwatch.ElapsedMilliseconds);
+ this.timeProvider.GetElapsedTime(this.startTime).TotalMilliseconds);
return Task.CompletedTask;
}
}
diff --git a/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ServiceCollectionExtensions.cs b/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ServiceCollectionExtensions.cs
index be0550117..555c73ad7 100644
--- a/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ServiceCollectionExtensions.cs
+++ b/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ServiceCollectionExtensions.cs
@@ -37,6 +37,7 @@ public static IServiceCollection AddConsoleAppService(this IServiceCollection se
services.AddConsoleAppContext(args);
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton(TimeProvider.System); ;
return services;
}
diff --git a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Hosting/ConsoleAppHostedServiceTest.cs b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Hosting/ConsoleAppHostedServiceTest.cs
index a5c71e9cc..ec2555a64 100644
--- a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Hosting/ConsoleAppHostedServiceTest.cs
+++ b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Hosting/ConsoleAppHostedServiceTest.cs
@@ -2,12 +2,15 @@
using Maris.ConsoleApp.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Time.Testing;
using Xunit.Abstractions;
namespace Maris.ConsoleApp.UnitTests.Hosting;
public class ConsoleAppHostedServiceTest(ITestOutputHelper testOutputHelper) : TestBase(testOutputHelper)
{
+ private TimeProvider systemTimeProvider = TimeProvider.System;
+
public static TheoryData GetContextsAndCommands()
{
// パターン1:正常終了するコマンド
@@ -50,7 +53,7 @@ public void Constructor_lifetimeがnull_ArgumentNullExceptionが発生する()
var logger = this.CreateTestLogger();
// Act
- var action = () => new ConsoleAppHostedService(lifetime!, settings, executor, logger);
+ var action = () => new ConsoleAppHostedService(lifetime!, settings, executor, logger, this.systemTimeProvider);
// Assert
Assert.Throws("lifetime", action);
@@ -69,7 +72,7 @@ public void Constructor_settingsがnull_ArgumentNullExceptionが発生する()
var logger = this.CreateTestLogger();
// Act
- var action = () => new ConsoleAppHostedService(lifetime, settings!, executor, logger);
+ var action = () => new ConsoleAppHostedService(lifetime, settings!, executor, logger, this.systemTimeProvider);
// Assert
Assert.Throws("settings", action);
@@ -85,7 +88,7 @@ public void Constructor_executorがnull_ArgumentNullExceptionが発生する()
var logger = this.CreateTestLogger();
// Act
- var action = () => new ConsoleAppHostedService(lifetime, settings, executor!, logger);
+ var action = () => new ConsoleAppHostedService(lifetime, settings, executor!, logger, this.systemTimeProvider);
// Assert
Assert.Throws("executor", action);
@@ -104,7 +107,7 @@ public void Constructor_loggerがnull_ArgumentNullExceptionが発生する()
ILogger? logger = null;
// Act
- var action = () => new ConsoleAppHostedService(lifetime, settings, executor, logger!);
+ var action = () => new ConsoleAppHostedService(lifetime, settings, executor, logger!, this.systemTimeProvider);
// Assert
Assert.Throws("logger", action);
@@ -127,7 +130,7 @@ public async Task StartAsync_コマンドが正常に完了する_コマンド
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger);
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider);
int actualExitCode = 0;
service.SetExitCode = (exitCode) => actualExitCode = exitCode;
var cancellationToken = new CancellationToken(false);
@@ -156,7 +159,7 @@ public async Task StartAsync_コマンドの入力値エラーがある_入力
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger);
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider);
int actualExitCode = 0;
service.SetExitCode = (exitCode) => actualExitCode = exitCode;
var cancellationToken = new CancellationToken(false);
@@ -185,7 +188,7 @@ public async Task StartAsync_コマンドの実行時に例外が発生する_
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger);
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider);
int actualExitCode = 0;
service.SetExitCode = (exitCode) => actualExitCode = exitCode;
var cancellationToken = new CancellationToken(false);
@@ -211,7 +214,7 @@ public async Task StartAsync_コマンドが完了_IHostApplicationLifetimeのSt
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger);
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider);
int actualExitCode = 0;
service.SetExitCode = (exitCode) => actualExitCode = exitCode;
var cancellationToken = new CancellationToken(false);
@@ -240,7 +243,7 @@ public async Task StartAsync_コマンドの開始について情報レベルで
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger)
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider)
{
SetExitCode = exitCode => { },
};
@@ -272,7 +275,7 @@ public async Task StartAsync_パラメーターの検証エラー_エラーの
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger)
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider)
{
SetExitCode = exitCode => { },
};
@@ -308,7 +311,7 @@ public async Task StartAsync_コマンドの実行エラー_エラーの情報
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger)
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider)
{
SetExitCode = exitCode => { },
};
@@ -342,7 +345,7 @@ public async Task StopAsync_コマンドの実行前に呼び出す_終了コー
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger);
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider);
var cancellationToken = new CancellationToken(false);
// Act
@@ -372,7 +375,7 @@ public async Task StopAsync_コマンドの実行完了後に呼び出す_コマ
var commandExecutorLogger = this.CreateTestLogger();
var executor = new CommandExecutor(manager, commandExecutorLogger);
var logger = this.CreateTestLogger();
- var service = new ConsoleAppHostedService(lifetime, settings, executor, logger);
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, this.systemTimeProvider);
var cancellationToken = new CancellationToken(false);
await service.StartAsync(cancellationToken);
@@ -386,6 +389,37 @@ public async Task StopAsync_コマンドの実行完了後に呼び出す_コマ
Assert.StartsWith($"sync-command コマンドのホストの処理が終了コード {exitCode} で完了しました。", record.Message);
}
+ [Fact]
+ public async Task StopAsync_コマンドの実行時間がログに出力される()
+ {
+ // Arrange
+ var lifetime = Mock.Of();
+ var settings = new ConsoleAppSettings();
+ var commandAttribute = new CommandAttribute("sync-command", typeof(SyncCommandImpl));
+ var parameter = new CommandParameter();
+ var context = new ConsoleAppContext(commandAttribute, parameter);
+ var exitCode = 456;
+ var command = new SyncCommandImpl(exitCode);
+ command.Initialize(context);
+ var managerMock = CreateCommandManagerMock(command);
+ var manager = managerMock.Object;
+ var commandExecutorLogger = this.CreateTestLogger();
+ var executor = new CommandExecutor(manager, commandExecutorLogger);
+ var logger = this.CreateTestLogger();
+ var fakeTimeProvider = new FakeTimeProvider();
+ var service = new ConsoleAppHostedService(lifetime, settings, executor, logger, fakeTimeProvider);
+ var cancellationToken = new CancellationToken(false);
+ await service.StartAsync(cancellationToken);
+
+ // Act
+ fakeTimeProvider.Advance(TimeSpan.FromMilliseconds(500));
+ await service.StopAsync(cancellationToken);
+
+ // Assert
+ var record = this.LogCollector.LatestRecord;
+ Assert.Contains($"実行時間は 500 ms でした。", record.Message);
+ }
+
private static Mock CreateCommandManagerMock(CommandBase? creatingCommand = null)
{
var command = creatingCommand ?? new TestCommand();
diff --git a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Hosting/ServiceCollectionExtensionsTest.cs b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Hosting/ServiceCollectionExtensionsTest.cs
index 08612af04..5d1c5bda9 100644
--- a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Hosting/ServiceCollectionExtensionsTest.cs
+++ b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Hosting/ServiceCollectionExtensionsTest.cs
@@ -53,6 +53,10 @@ public void AddConsoleAppService_必要なサービスが登録される()
{
Assert.Equal(typeof(ICommandManager), service.ServiceType);
Assert.Equal(typeof(DefaultCommandManager), service.ImplementationType);
+ },
+ service =>
+ {
+ Assert.Equal(typeof(TimeProvider), service.ServiceType);
});
}
diff --git a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Maris.ConsoleApp.UnitTests.csproj b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Maris.ConsoleApp.UnitTests.csproj
index 9aeff6e4e..66822e71d 100644
--- a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Maris.ConsoleApp.UnitTests.csproj
+++ b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.UnitTests/Maris.ConsoleApp.UnitTests.csproj
@@ -6,6 +6,7 @@
+
diff --git a/samples/Dressca/dressca-backend/Directory.Packages.props b/samples/Dressca/dressca-backend/Directory.Packages.props
index c8a807182..94c59eb2b 100644
--- a/samples/Dressca/dressca-backend/Directory.Packages.props
+++ b/samples/Dressca/dressca-backend/Directory.Packages.props
@@ -11,6 +11,7 @@
+
diff --git a/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs b/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
index d758284d0..e2f1fb866 100644
--- a/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
+++ b/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
@@ -12,6 +12,8 @@ public class Order
private readonly Account? account;
private string? buyerId;
private ShipTo? shipToAddress;
+ private DateTimeOffset orderDate;
+ private TimeProvider timeProvider;
///
/// クラスの新しいインスタンスを初期化します。
@@ -46,11 +48,52 @@ public Order(string buyerId, ShipTo shipToAddress, List orderItems)
this.DeliveryCharge = this.account.GetDeliveryCharge();
this.ConsumptionTax = this.account.GetConsumptionTax();
this.TotalPrice = this.account.GetTotalPrice();
+ this.timeProvider = TimeProvider.System;
+ this.orderDate = this.timeProvider.GetLocalNow();
+ }
+
+ ///
+ /// クラスの新しいインスタンスをテスト用に初期化します。
+ ///
+ /// 購入者 Id 。
+ /// 配送先住所。
+ /// 注文アイテムのリスト。
+ /// 日時のプロバイダ。
+ ///
+ ///
+ /// - が または空の文字列です。
+ /// - が または空のリストです。
+ ///
+ ///
+ ///
+ ///
+ /// - が です。
+ ///
+ ///
+ internal Order(string buyerId, ShipTo shipToAddress, List orderItems, TimeProvider timeProvider)
+ {
+ if (orderItems is null || !orderItems.Any())
+ {
+ throw new ArgumentException(Messages.ArgumentIsNullOrEmptyList, nameof(orderItems));
+ }
+
+ this.BuyerId = buyerId;
+ this.ShipToAddress = shipToAddress;
+ this.orderItems = orderItems;
+ this.account = new Account(orderItems.Select(item => new AccountItem(item.Quantity, item.UnitPrice)));
+ this.ConsumptionTaxRate = Account.ConsumptionTaxRate;
+ this.TotalItemsPrice = this.account.GetItemsTotalPrice();
+ this.DeliveryCharge = this.account.GetDeliveryCharge();
+ this.ConsumptionTax = this.account.GetConsumptionTax();
+ this.TotalPrice = this.account.GetTotalPrice();
+ this.timeProvider = timeProvider;
+ this.orderDate = this.timeProvider.GetLocalNow();
}
private Order()
{
// Required by EF Core.
+ this.timeProvider = TimeProvider.System;
}
///
@@ -81,7 +124,11 @@ private set
/// 注文日を取得します。
/// このクラスのインスタンスが生成されたシステム日時が自動的に設定されます.
///
- public DateTimeOffset OrderDate { get; private set; } = DateTimeOffset.Now;
+ public DateTimeOffset OrderDate
+ {
+ get => this.orderDate;
+ private set => this.orderDate = value;
+ }
///
/// お届け先を取得します。
diff --git a/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/ApplicationCore/Ordering/OrderTest.cs b/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/ApplicationCore/Ordering/OrderTest.cs
index 378d808dc..08e2286cb 100644
--- a/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/ApplicationCore/Ordering/OrderTest.cs
+++ b/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/ApplicationCore/Ordering/OrderTest.cs
@@ -1,4 +1,5 @@
using Dressca.ApplicationCore.Ordering;
+using Microsoft.Extensions.Time.Testing;
namespace Dressca.UnitTests.ApplicationCore.Ordering;
@@ -171,6 +172,24 @@ public void HasMatchingBuyerId_指定の購入者Idと一致しない_false()
Assert.False(result);
}
+ [Fact]
+ public void Constructor_OrderDateが注文時のシステム時刻と等しい()
+ {
+ // Arrange
+ var buyerId = Guid.NewGuid().ToString("D");
+ var shipTo = CreateDefaultShipTo();
+ var items = CreateDefaultOrderItems();
+ var fakeTimeProvider = new FakeTimeProvider();
+ var testOrderTime = new DateTimeOffset(2024, 4, 1, 00, 00, 00, new TimeSpan(9, 0, 0));
+ fakeTimeProvider.SetUtcNow(testOrderTime);
+
+ // Act
+ var order = new Order(buyerId, shipTo, items, fakeTimeProvider);
+
+ // Assert
+ Assert.Equal(testOrderTime, order.OrderDate);
+ }
+
private static Address CreateDefaultAddress()
{
const string defaultPostalCode = "100-8924";
diff --git a/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Dressca.UnitTests.csproj b/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Dressca.UnitTests.csproj
index 498fca40b..32472ae36 100644
--- a/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Dressca.UnitTests.csproj
+++ b/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Dressca.UnitTests.csproj
@@ -10,6 +10,7 @@
+
From 2b7c377bef1c359c69445be18908d88d5b313464 Mon Sep 17 00:00:00 2001
From: kentah <158997636+KentaHizume@users.noreply.github.com>
Date: Tue, 27 Feb 2024 11:07:55 +0900
Subject: [PATCH 02/17] =?UTF-8?q?ObjectState=E3=81=AB=E3=81=A4=E3=81=84?=
=?UTF-8?q?=E3=81=A6TimeProvider=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=99?=
=?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ServiceCollectionExtensions.cs | 2 +-
.../Maris.ConsoleApp.IntegrationTests.csproj | 5 +++++
.../ScopeTests/ObjectState.cs | 9 +++++++--
.../ScopeTests/TestObjectBase.cs | 19 +++++++++++++------
4 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ServiceCollectionExtensions.cs b/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ServiceCollectionExtensions.cs
index 555c73ad7..5b47a4340 100644
--- a/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ServiceCollectionExtensions.cs
+++ b/samples/ConsoleAppWithDI/solution/src/Maris.ConsoleApp.Hosting/ServiceCollectionExtensions.cs
@@ -37,7 +37,7 @@ public static IServiceCollection AddConsoleAppService(this IServiceCollection se
services.AddConsoleAppContext(args);
services.AddSingleton();
services.AddSingleton();
- services.AddSingleton(TimeProvider.System); ;
+ services.AddSingleton(TimeProvider.System);
return services;
}
diff --git a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/Maris.ConsoleApp.IntegrationTests.csproj b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/Maris.ConsoleApp.IntegrationTests.csproj
index 033afafc3..6e49dd5cb 100644
--- a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/Maris.ConsoleApp.IntegrationTests.csproj
+++ b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/Maris.ConsoleApp.IntegrationTests.csproj
@@ -1,7 +1,12 @@
+
+ 3cef1c30-b156-4846-b3a3-5b04b23926db
+
+
+
all
diff --git a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/ScopeTests/ObjectState.cs b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/ScopeTests/ObjectState.cs
index c69ddb111..7f18fce7f 100644
--- a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/ScopeTests/ObjectState.cs
+++ b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/ScopeTests/ObjectState.cs
@@ -2,11 +2,16 @@
internal class ObjectState
{
- internal ObjectState(Guid objectId, Type objectType, Condition condition)
+ private readonly TimeProvider timeProvider;
+ private DateTime createDate;
+
+ internal ObjectState(Guid objectId, Type objectType, Condition condition, TimeProvider timeProvider)
{
this.ObjectId = objectId;
this.ObjectType = objectType;
this.Condition = condition;
+ this.timeProvider = timeProvider;
+ this.createDate = timeProvider.GetLocalNow().UtcDateTime;
}
internal Guid ObjectId { get; private set; }
@@ -15,5 +20,5 @@ internal ObjectState(Guid objectId, Type objectType, Condition condition)
internal Condition Condition { get; private set; }
- internal DateTime CreateDate { get; } = DateTime.Now;
+ internal DateTime CreateDate { get => this.createDate; }
}
diff --git a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/ScopeTests/TestObjectBase.cs b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/ScopeTests/TestObjectBase.cs
index 4e490d2d6..0ca39a76c 100644
--- a/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/ScopeTests/TestObjectBase.cs
+++ b/samples/ConsoleAppWithDI/solution/tests/Maris.ConsoleApp.IntegrationTests/ScopeTests/TestObjectBase.cs
@@ -1,15 +1,21 @@
-namespace Maris.ConsoleApp.IntegrationTests.ScopeTests;
+using Microsoft.Extensions.Time.Testing;
+
+namespace Maris.ConsoleApp.IntegrationTests.ScopeTests;
internal class TestObjectBase : IDisposable
{
private readonly Guid objectId = Guid.NewGuid();
private bool disposed;
+ private TimeProvider fakeTimeProvider = new FakeTimeProvider();
- public TestObjectBase() =>
+ public TestObjectBase()
+ {
ObjectStateHistory.Add(new(
this.objectId,
this.GetType(),
- Condition.Creating));
+ Condition.Creating,
+ this.fakeTimeProvider));
+ }
public void Dispose()
{
@@ -21,16 +27,17 @@ protected void LogHistory() =>
ObjectStateHistory.Add(new(
this.objectId,
this.GetType(),
- this.disposed ? Condition.AlreadyDisposed : Condition.Alive));
+ this.disposed ? Condition.AlreadyDisposed : Condition.Alive,
+ this.fakeTimeProvider));
protected virtual void Dispose(bool disposing)
{
- ObjectStateHistory.Add(new(this.objectId, this.GetType(), Condition.ObjectDisposing));
+ ObjectStateHistory.Add(new(this.objectId, this.GetType(), Condition.ObjectDisposing, this.fakeTimeProvider));
if (!this.disposed)
{
this.disposed = true;
- ObjectStateHistory.Add(new(this.objectId, this.GetType(), Condition.ObjectDisposed));
+ ObjectStateHistory.Add(new(this.objectId, this.GetType(), Condition.ObjectDisposed, this.fakeTimeProvider));
}
}
}
From d8bffdba9df1d8787ef6bfe3798c3d84ebe56957 Mon Sep 17 00:00:00 2001
From: kentah <158997636+KentaHizume@users.noreply.github.com>
Date: Tue, 27 Feb 2024 11:35:53 +0900
Subject: [PATCH 03/17] =?UTF-8?q?FakeTimeProvider=E3=82=92=E4=BD=BF?=
=?UTF-8?q?=E7=94=A8=E3=81=97=E3=81=A6=E6=97=A5=E6=99=82=E3=82=92=E8=A8=AD?=
=?UTF-8?q?=E5=AE=9A=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Web/Baskets/HttpContextExtensionsTest.cs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Web/Baskets/HttpContextExtensionsTest.cs b/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Web/Baskets/HttpContextExtensionsTest.cs
index 0b29ecfcd..90f79406b 100644
--- a/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Web/Baskets/HttpContextExtensionsTest.cs
+++ b/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Web/Baskets/HttpContextExtensionsTest.cs
@@ -1,5 +1,6 @@
using Dressca.Web.Baskets;
using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Time.Testing;
namespace Dressca.UnitTests.Web.Baskets;
@@ -24,9 +25,10 @@ public void GetBuyerId_購入者IdがHttpContextに存在しない_新たにGuid
public void GetBuyerId_購入者Idが文字列型ではない_新たにGuid形式の購入者Idが発行される()
{
// Arrange
+ var fakeTimeProvider = new FakeTimeProvider();
var items = new Dictionary
+ /// Cookie のキー名。
/// 日時のプロバイダ。通常はシステム日時。
- /// Cookie のキー名。未指定時は "Dressca-Bid" 。
///
/// が です。
///
- internal BuyerIdFilterAttribute(TimeProvider timeProvider, string buyerIdCookieName = DefaultBuyerIdCookieName)
+ internal BuyerIdFilterAttribute(string buyerIdCookieName, TimeProvider timeProvider)
{
- this.timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
this.buyerIdCookieName = buyerIdCookieName ?? throw new ArgumentNullException(nameof(buyerIdCookieName));
+ this.timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
}
///
diff --git a/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Web/Baskets/BuyerIdFilterAttributeTest.cs b/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Web/Baskets/BuyerIdFilterAttributeTest.cs
index 027ab651a..8c5211c8f 100644
--- a/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Web/Baskets/BuyerIdFilterAttributeTest.cs
+++ b/samples/Dressca/dressca-backend/tests/Dressca.UnitTests/Web/Baskets/BuyerIdFilterAttributeTest.cs
@@ -15,6 +15,7 @@ public class BuyerIdFilterAttributeTest
public void Cookieの有効期限は7日間()
{
// Arrange
+ var buyerIdCookieName = "Dressca-Bid";
var httpContext = new DefaultHttpContext();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
var context = new ActionExecutedContext(actionContext, new List(), Mock.Of());
@@ -23,7 +24,7 @@ public void Cookieの有効期限は7日間()
fakeTimeProvider.SetUtcNow(testCookieCreatedDateTime);
var expectedDateTime = testCookieCreatedDateTime.AddDays(7);
var formattedExpectedDateTime = expectedDateTime.ToString("ddd, dd MMM yyyy HH:mm:ss 'GMT'", CultureInfo.InvariantCulture);
- var filter = new BuyerIdFilterAttribute(fakeTimeProvider);
+ var filter = new BuyerIdFilterAttribute(buyerIdCookieName, fakeTimeProvider);
// Act
filter.OnActionExecuted(context);
From d3d6a5634024f93fc6676d00f8fef3a1f862237f Mon Sep 17 00:00:00 2001
From: kentah <158997636+KentaHizume@users.noreply.github.com>
Date: Thu, 29 Feb 2024 16:17:49 +0900
Subject: [PATCH 13/17] =?UTF-8?q?BuyerIdFilterAttribute=E3=81=AEXML?=
=?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=E4=B8=8D=E6=95=B4?=
=?UTF-8?q?=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/samples/Dressca/dressca-backend/src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs b/samples/Dressca/dressca-backend/src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs
index 3940e747b..93452cdb6 100644
--- a/samples/Dressca/dressca-backend/src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs
+++ b/samples/Dressca/dressca-backend/src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs
@@ -22,12 +22,9 @@ public class BuyerIdFilterAttribute : ActionFilterAttribute
private readonly TimeProvider timeProvider;
///
- /// クラスの新しいインスタンスを初期化します。
+ /// no クラスの新しいインスタンスを初期化します。
///
/// Cookie のキー名。未指定時は "Dressca-Bid" 。
- ///
- /// が です。
- ///
public BuyerIdFilterAttribute(string buyerIdCookieName = DefaultBuyerIdCookieName)
: this(buyerIdCookieName, TimeProvider.System)
{
@@ -40,7 +37,10 @@ public BuyerIdFilterAttribute(string buyerIdCookieName = DefaultBuyerIdCookieNam
/// Cookie のキー名。
/// 日時のプロバイダ。通常はシステム日時。
///
- /// が です。
+ ///
+ /// が です。
+ /// が です。
+ ///
///
internal BuyerIdFilterAttribute(string buyerIdCookieName, TimeProvider timeProvider)
{
From 8c69c92670be046d5a47aab4509f988070d31fd2 Mon Sep 17 00:00:00 2001
From: kentah <158997636+KentaHizume@users.noreply.github.com>
Date: Fri, 1 Mar 2024 09:05:20 +0900
Subject: [PATCH 14/17] =?UTF-8?q?XML=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?=
=?UTF-8?q?=E3=81=AE=E8=AA=A4=E8=A8=98=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/Dressca/dressca-backend/src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs b/samples/Dressca/dressca-backend/src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs
index 93452cdb6..89b1f9fa6 100644
--- a/samples/Dressca/dressca-backend/src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs
+++ b/samples/Dressca/dressca-backend/src/Dressca.Web/Baskets/BuyerIdFilterAttribute.cs
@@ -22,7 +22,7 @@ public class BuyerIdFilterAttribute : ActionFilterAttribute
private readonly TimeProvider timeProvider;
///
- /// no クラスの新しいインスタンスを初期化します。
+ /// クラスの新しいインスタンスを初期化します。
///
/// Cookie のキー名。未指定時は "Dressca-Bid" 。
public BuyerIdFilterAttribute(string buyerIdCookieName = DefaultBuyerIdCookieName)
From 2af3ce5ae9e086f14ca202a63c46e58305a2d942 Mon Sep 17 00:00:00 2001
From: kentah <158997636+KentaHizume@users.noreply.github.com>
Date: Fri, 1 Mar 2024 10:01:17 +0900
Subject: [PATCH 15/17] =?UTF-8?q?internal=E3=83=A1=E3=82=BD=E3=83=83?=
=?UTF-8?q?=E3=83=89=E3=81=AE=E5=BC=95=E6=95=B0=E3=81=AB=E5=AF=BE=E3=81=97?=
=?UTF-8?q?=E3=81=A6=E3=82=82NULL=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF?=
=?UTF-8?q?=E3=82=92=E8=A1=8C=E3=81=86=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Dressca.ApplicationCore/Ordering/Order.cs | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs b/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
index 36baab555..fc1db6f6d 100644
--- a/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
+++ b/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
@@ -20,17 +20,6 @@ public class Order
/// 購入者 Id 。
/// 配送先住所。
/// 注文アイテムのリスト。
- ///
- ///
- /// - が または空の文字列です。
- /// - が または空のリストです。
- ///
- ///
- ///
- ///
- /// - が です。
- ///
- ///
public Order(string buyerId, ShipTo shipToAddress, List orderItems)
: this(buyerId, shipToAddress, orderItems, TimeProvider.System)
{
@@ -53,6 +42,7 @@ public Order(string buyerId, ShipTo shipToAddress, List orderItems)
///
///
/// - が です。
+ /// - が です。
///
///
internal Order(string buyerId, ShipTo shipToAddress, List orderItems, TimeProvider timeProvider)
@@ -62,8 +52,8 @@ internal Order(string buyerId, ShipTo shipToAddress, List orderItems,
throw new ArgumentException(Messages.ArgumentIsNullOrEmptyList, nameof(orderItems));
}
- this.BuyerId = buyerId;
- this.ShipToAddress = shipToAddress;
+ this.BuyerId = string.IsNullOrEmpty(buyerId) ? throw new ArgumentException(Messages.ArgumentIsNullOrWhiteSpace, nameof(buyerId)) : buyerId;
+ this.ShipToAddress = shipToAddress ?? throw new ArgumentNullException(nameof(shipToAddress));
this.orderItems = orderItems;
this.account = new Account(orderItems.Select(item => new AccountItem(item.Quantity, item.UnitPrice)));
this.ConsumptionTaxRate = Account.ConsumptionTaxRate;
@@ -71,7 +61,7 @@ internal Order(string buyerId, ShipTo shipToAddress, List orderItems,
this.DeliveryCharge = this.account.GetDeliveryCharge();
this.ConsumptionTax = this.account.GetConsumptionTax();
this.TotalPrice = this.account.GetTotalPrice();
- this.timeProvider = timeProvider;
+ this.timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
this.OrderDate = this.timeProvider.GetLocalNow();
}
From d841d80dffad8d1cea9cf347157ec470516f61b2 Mon Sep 17 00:00:00 2001
From: kentah <158997636+KentaHizume@users.noreply.github.com>
Date: Fri, 1 Mar 2024 10:42:08 +0900
Subject: [PATCH 16/17] =?UTF-8?q?Revert=20"internal=E3=83=A1=E3=82=BD?=
=?UTF-8?q?=E3=83=83=E3=83=89=E3=81=AE=E5=BC=95=E6=95=B0=E3=81=AB=E5=AF=BE?=
=?UTF-8?q?=E3=81=97=E3=81=A6=E3=82=82NULL=E3=83=81=E3=82=A7=E3=83=83?=
=?UTF-8?q?=E3=82=AF=E3=82=92=E8=A1=8C=E3=81=86=E3=82=88=E3=81=86=E4=BF=AE?=
=?UTF-8?q?=E6=AD=A3"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 2af3ce5ae9e086f14ca202a63c46e58305a2d942.
---
.../Dressca.ApplicationCore/Ordering/Order.cs | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs b/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
index fc1db6f6d..36baab555 100644
--- a/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
+++ b/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
@@ -20,6 +20,17 @@ public class Order
/// 購入者 Id 。
/// 配送先住所。
/// 注文アイテムのリスト。
+ ///
+ ///
+ /// - が または空の文字列です。
+ /// - が または空のリストです。
+ ///
+ ///
+ ///
+ ///
+ /// - が です。
+ ///
+ ///
public Order(string buyerId, ShipTo shipToAddress, List orderItems)
: this(buyerId, shipToAddress, orderItems, TimeProvider.System)
{
@@ -42,7 +53,6 @@ public Order(string buyerId, ShipTo shipToAddress, List orderItems)
///
///
/// - が です。
- /// - が です。
///
///
internal Order(string buyerId, ShipTo shipToAddress, List orderItems, TimeProvider timeProvider)
@@ -52,8 +62,8 @@ internal Order(string buyerId, ShipTo shipToAddress, List orderItems,
throw new ArgumentException(Messages.ArgumentIsNullOrEmptyList, nameof(orderItems));
}
- this.BuyerId = string.IsNullOrEmpty(buyerId) ? throw new ArgumentException(Messages.ArgumentIsNullOrWhiteSpace, nameof(buyerId)) : buyerId;
- this.ShipToAddress = shipToAddress ?? throw new ArgumentNullException(nameof(shipToAddress));
+ this.BuyerId = buyerId;
+ this.ShipToAddress = shipToAddress;
this.orderItems = orderItems;
this.account = new Account(orderItems.Select(item => new AccountItem(item.Quantity, item.UnitPrice)));
this.ConsumptionTaxRate = Account.ConsumptionTaxRate;
@@ -61,7 +71,7 @@ internal Order(string buyerId, ShipTo shipToAddress, List orderItems,
this.DeliveryCharge = this.account.GetDeliveryCharge();
this.ConsumptionTax = this.account.GetConsumptionTax();
this.TotalPrice = this.account.GetTotalPrice();
- this.timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
+ this.timeProvider = timeProvider;
this.OrderDate = this.timeProvider.GetLocalNow();
}
From da32f4f423dcc14c826b857b84dd644178bd40bc Mon Sep 17 00:00:00 2001
From: kentah <158997636+KentaHizume@users.noreply.github.com>
Date: Fri, 1 Mar 2024 10:47:54 +0900
Subject: [PATCH 17/17] =?UTF-8?q?timeProvider=E3=81=AB=E5=AF=BE=E3=81=99?=
=?UTF-8?q?=E3=82=8BNULL=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E3=82=92?=
=?UTF-8?q?=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/Dressca.ApplicationCore/Ordering/Order.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs b/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
index 36baab555..5c79d9292 100644
--- a/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
+++ b/samples/Dressca/dressca-backend/src/Dressca.ApplicationCore/Ordering/Order.cs
@@ -53,6 +53,7 @@ public Order(string buyerId, ShipTo shipToAddress, List orderItems)
///
///
/// - が です。
+ /// - が です。
///
///
internal Order(string buyerId, ShipTo shipToAddress, List orderItems, TimeProvider timeProvider)
@@ -71,7 +72,7 @@ internal Order(string buyerId, ShipTo shipToAddress, List orderItems,
this.DeliveryCharge = this.account.GetDeliveryCharge();
this.ConsumptionTax = this.account.GetConsumptionTax();
this.TotalPrice = this.account.GetTotalPrice();
- this.timeProvider = timeProvider;
+ this.timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
this.OrderDate = this.timeProvider.GetLocalNow();
}