Skip to content

Commit 16ee484

Browse files
authored
fix: Remove DateTime in favour of TimeProvder and DateTimeOffset (#238)
1 parent 44f1390 commit 16ee484

39 files changed

+380
-233
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ csharp_style_prefer_null_check_over_type_check = true : suggestion
110110
csharp_style_implicit_object_creation_when_type_is_apparent = true : suggestion
111111

112112
# primary constructors (C# 12+)
113-
csharp_style_prefer_primary_constructors = true : suggestion
113+
csharp_style_prefer_primary_constructors = true : warning
114114

115115
# collection expressions (C# 12+)
116116
dotnet_style_prefer_collection_expression = true : suggestion

src/AzureEventGridSimulator.Tests/Domain/Services/Dashboard/EventHistoryServiceTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public void RecordDeliveryAttempt_UpdatesDeliveryStatus()
115115
var attempt = new DeliveryAttempt
116116
{
117117
AttemptNumber = 1,
118-
AttemptTime = DateTime.UtcNow,
118+
AttemptTime = DateTimeOffset.UtcNow,
119119
Outcome = DeliveryOutcome.Success,
120120
HttpStatusCode = 200,
121121
};
@@ -136,7 +136,7 @@ public void RecordDeliveryAttempt_NonExistingEvent_DoesNotThrow()
136136
var attempt = new DeliveryAttempt
137137
{
138138
AttemptNumber = 1,
139-
AttemptTime = DateTime.UtcNow,
139+
AttemptTime = DateTimeOffset.UtcNow,
140140
Outcome = DeliveryOutcome.Success,
141141
};
142142

@@ -283,7 +283,7 @@ private static SimulatorEvent CreateTestEvent(string id)
283283
Id = id,
284284
Subject = "/test/subject",
285285
EventType = "Test.EventType",
286-
EventTime = DateTime.UtcNow.ToString("o"),
286+
EventTime = DateTimeOffset.UtcNow.ToString("o"),
287287
DataVersion = "1.0",
288288
Data = new { Property = "Value" },
289289
}

src/AzureEventGridSimulator.Tests/Domain/Services/Dashboard/EventHistoryStoreTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ private static EventHistoryRecord CreateTestRecord(string id, string topicName =
258258
EventType = "Test.EventType",
259259
Subject = "/test/subject",
260260
Source = "/test/source",
261-
EventTime = DateTime.UtcNow.ToString("o"),
261+
EventTime = DateTimeOffset.UtcNow.ToString("o"),
262262
InputSchema = EventSchema.EventGridSchema,
263263
PayloadJson = "{}",
264264
};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace AzureEventGridSimulator.Tests.Helpers;
2+
3+
/// <summary>
4+
/// A fake TimeProvider for testing time-dependent code.
5+
/// Allows tests to control the current time for deterministic behavior.
6+
/// </summary>
7+
public class FakeTimeProvider(DateTimeOffset startTime) : TimeProvider
8+
{
9+
private DateTimeOffset _utcNow = startTime;
10+
11+
public override DateTimeOffset GetUtcNow()
12+
{
13+
return _utcNow;
14+
}
15+
16+
/// <summary>
17+
/// Sets the current time to a specific value.
18+
/// </summary>
19+
public void SetUtcNow(DateTimeOffset value)
20+
{
21+
_utcNow = value;
22+
}
23+
24+
/// <summary>
25+
/// Advances the current time by the specified duration.
26+
/// </summary>
27+
public void Advance(TimeSpan duration)
28+
{
29+
_utcNow = _utcNow.Add(duration);
30+
}
31+
}

src/AzureEventGridSimulator.Tests/UnitTests/CloudEvents/CloudEventSchemaFormatterTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ public void GivenEventGridEvent_WhenSerializedAsCloudEvent_ThenConvertedCorrectl
7272
EventType = "Test.Event.Type",
7373
EventTime = "2025-01-15T10:30:00Z",
7474
Data = new { Property = "Value" },
75-
Topic = "/test/topic",
7675
};
76+
eventGridEvent.SetTopic("/test/topic");
7777

7878
var simulatorEvent = SimulatorEvent.FromEventGridEvent(eventGridEvent);
7979
var json = _formatter.Serialize(simulatorEvent);

src/AzureEventGridSimulator.Tests/UnitTests/CloudEvents/SimulatorEventTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public void GivenEventGridEvent_WhenWrappedInSimulatorEvent_ThenPropertiesMapped
1818
EventTime = "2025-01-15T10:30:00Z",
1919
Data = new { Property = "Value" },
2020
DataVersion = "1.0",
21-
Topic = "/test/topic",
2221
};
22+
eventGridEvent.SetTopic("/test/topic");
2323

2424
var simulatorEvent = SimulatorEvent.FromEventGridEvent(eventGridEvent);
2525

src/AzureEventGridSimulator.Tests/UnitTests/Commands/SendNotificationEventsToSubscriberCommandHandlerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ private static SimulatorEvent CreateTestEventGridEvent(string id)
407407
Id = id,
408408
Subject = "/test/subject",
409409
EventType = "Test.EventType",
410-
EventTime = DateTime.UtcNow.ToString("o"),
410+
EventTime = DateTimeOffset.UtcNow.ToString("o"),
411411
DataVersion = "1.0",
412412
Data = new { Property = "Value" },
413413
}

src/AzureEventGridSimulator.Tests/UnitTests/Commands/ValidateSubscriptionCommandHandlerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class ValidateSubscriptionCommandHandlerTests
1616
public ValidateSubscriptionCommandHandlerTests()
1717
{
1818
_logger = Substitute.For<ILogger<ValidateSubscriptionCommandHandler>>();
19-
_handler = new ValidateSubscriptionCommandHandler(_logger);
19+
_handler = new ValidateSubscriptionCommandHandler(TimeProvider.System, _logger);
2020
}
2121

2222
[Fact]

src/AzureEventGridSimulator.Tests/UnitTests/EventGrid/EventGridSchemaFormatterTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace AzureEventGridSimulator.Tests.UnitTests.EventGrid;
99
[Trait("Category", "unit")]
1010
public class EventGridSchemaFormatterTests
1111
{
12-
private readonly EventGridSchemaFormatter _formatter = new();
12+
private readonly EventGridSchemaFormatter _formatter = new(TimeProvider.System);
1313

1414
[Fact]
1515
public void GivenEventGridEvent_WhenSerialized_ThenJsonContainsAllFields()
@@ -22,9 +22,9 @@ public void GivenEventGridEvent_WhenSerialized_ThenJsonContainsAllFields()
2222
EventTime = "2025-01-15T10:30:00Z",
2323
Data = new { Property = "Value" },
2424
DataVersion = "1.0",
25-
Topic = "/test/topic",
2625
MetadataVersion = "1",
2726
};
27+
eventGridEvent.SetTopic("/test/topic");
2828

2929
var simulatorEvent = SimulatorEvent.FromEventGridEvent(eventGridEvent);
3030
var json = _formatter.Serialize(simulatorEvent);

src/AzureEventGridSimulator.Tests/UnitTests/EventGrid/EventGridValidationTests.cs

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Text.Json;
12
using AzureEventGridSimulator.Domain.Entities;
23
using Shouldly;
34
using Xunit;
@@ -258,36 +259,55 @@ string metadataVersion
258259
public void GivenEventWithNonNullTopic_WhenValidated_ThenExceptionThrown()
259260
{
260261
// Topic should be null/empty when publishing - it's set by the service
261-
var eventGridEvent = new EventGridEvent
262-
{
263-
Id = "test-id-123",
264-
Subject = "/test/subject",
265-
EventType = "Test.EventType",
266-
EventTime = "2025-01-15T10:30:00Z",
267-
Topic = "/subscriptions/some/topic",
268-
};
269-
270-
var exception = Should.Throw<InvalidOperationException>(() => eventGridEvent.Validate());
262+
// Use JSON deserialization to simulate a publisher sending a Topic value
263+
var json = """
264+
{
265+
"id": "test-id-123",
266+
"subject": "/test/subject",
267+
"eventType": "Test.EventType",
268+
"eventTime": "2025-01-15T10:30:00Z",
269+
"topic": "/subscriptions/some/topic"
270+
}
271+
""";
272+
var eventGridEvent = JsonSerializer.Deserialize<EventGridEvent>(json);
273+
274+
var exception = Should.Throw<InvalidOperationException>(() => eventGridEvent!.Validate());
271275
exception.Message.ShouldContain("Topic");
272276
}
273277

274-
[Theory]
275-
[InlineData(null)]
276-
[InlineData("")]
277-
public void GivenEventWithNullOrEmptyTopic_WhenValidated_ThenNoExceptionThrown(string topic)
278+
[Fact]
279+
public void GivenEventWithNullTopic_WhenValidated_ThenNoExceptionThrown()
278280
{
281+
// Topic defaults to null when not set
279282
var eventGridEvent = new EventGridEvent
280283
{
281284
Id = "test-id-123",
282285
Subject = "/test/subject",
283286
EventType = "Test.EventType",
284287
EventTime = "2025-01-15T10:30:00Z",
285-
Topic = topic,
286288
};
287289

288290
Should.NotThrow(() => eventGridEvent.Validate());
289291
}
290292

293+
[Fact]
294+
public void GivenEventWithEmptyTopic_WhenValidated_ThenNoExceptionThrown()
295+
{
296+
// Use JSON deserialization to set empty Topic
297+
var json = """
298+
{
299+
"id": "test-id-123",
300+
"subject": "/test/subject",
301+
"eventType": "Test.EventType",
302+
"eventTime": "2025-01-15T10:30:00Z",
303+
"topic": ""
304+
}
305+
""";
306+
var eventGridEvent = JsonSerializer.Deserialize<EventGridEvent>(json);
307+
308+
Should.NotThrow(() => eventGridEvent!.Validate());
309+
}
310+
291311
[Fact]
292312
public void GivenEventWithNullData_WhenValidated_ThenNoExceptionThrown()
293313
{

0 commit comments

Comments
 (0)