PQSoft.JsonComparer.AwesomeAssertions
1.1.0-beta.3
dotnet add package PQSoft.JsonComparer.AwesomeAssertions --version 1.1.0-beta.3
NuGet\Install-Package PQSoft.JsonComparer.AwesomeAssertions -Version 1.1.0-beta.3
<PackageReference Include="PQSoft.JsonComparer.AwesomeAssertions" Version="1.1.0-beta.3" />
<PackageVersion Include="PQSoft.JsonComparer.AwesomeAssertions" Version="1.1.0-beta.3" />
<PackageReference Include="PQSoft.JsonComparer.AwesomeAssertions" />
paket add PQSoft.JsonComparer.AwesomeAssertions --version 1.1.0-beta.3
#r "nuget: PQSoft.JsonComparer.AwesomeAssertions, 1.1.0-beta.3"
#:package PQSoft.JsonComparer.AwesomeAssertions@1.1.0-beta.3
#addin nuget:?package=PQSoft.JsonComparer.AwesomeAssertions&version=1.1.0-beta.3&prerelease
#tool nuget:?package=PQSoft.JsonComparer.AwesomeAssertions&version=1.1.0-beta.3&prerelease
PQSoft.JsonComparer.AwesomeAssertions
AwesomeAssertions extensions for JSON comparison that integrate seamlessly with the JsonComparer functionality.
Why Use This Library?
The Problem with Traditional JSON Testing
Traditional JSON testing approaches have significant limitations:
// ❌ Brittle - breaks when server generates new IDs or timestamps
Assert.Equal("""{"id": "12345", "createdAt": "2024-01-01T10:00:00Z"}""", actualJson);
// ❌ Verbose - requires manual parsing and individual property checks
var parsed = JsonSerializer.Deserialize<ApiResponse>(actualJson);
Assert.Equal("John", parsed.Name);
Assert.NotNull(parsed.Id);
Assert.True(parsed.CreatedAt > DateTime.UtcNow.AddMinutes(-1));
The Solution: Smart JSON Assertions
This library provides intelligent JSON testing that handles dynamic values while maintaining strict validation:
// ✅ Flexible - extracts dynamic values while validating structure
actualJson.AsJsonString().Should().FullyMatch("""
{
"id": "[[USER_ID]]",
"name": "John",
"createdAt": "{{UTCNOW()}}"
}
""");
Key Testing Scenarios
1. API Response Validation
Perfect for testing REST APIs where responses contain generated IDs, timestamps, and tokens:
// Test user creation endpoint
string createUserResponse = await httpClient.PostAsync("/users", userData);
createUserResponse.AsJsonString().Should().FullyMatch("""
{
"user": {
"id": "[[USER_ID]]",
"email": "test@example.com",
"createdAt": "{{UTCNOW()}}",
"status": "active"
},
"authToken": "[[AUTH_TOKEN]]"
}
""");
// Extract values for subsequent tests
var userId = result.ExtractedValues["USER_ID"];
var token = result.ExtractedValues["AUTH_TOKEN"];
2. Database Integration Testing
Validate database operations while handling auto-generated fields:
// After inserting a record
var dbRecord = await repository.GetByIdAsync(newId);
var json = JsonSerializer.Serialize(dbRecord);
json.AsJsonString().Should().FullyMatch("""
{
"id": "[[RECORD_ID]]",
"name": "Test Record",
"createdAt": "{{UTCNOW()}}",
"updatedAt": "{{UTCNOW()}}",
"version": 1
}
""");
3. Event-Driven Architecture Testing
Validate event payloads with dynamic correlation IDs and timestamps:
// Validate published event
eventPayload.AsJsonString().Should().FullyMatch("""
{
"eventId": "{{GUID()}}",
"correlationId": "[[CORRELATION_ID]]",
"eventType": "UserCreated",
"timestamp": "{{UTCNOW()}}",
"data": {
"userId": "[[USER_ID]]",
"email": "user@example.com"
}
}
""");
4. Microservices Contract Testing
Ensure service contracts are maintained while allowing for implementation flexibility:
// Validate service response contract
serviceResponse.AsJsonString().Should().ContainSubset("""
{
"status": "success",
"data": {
"id": "[[RESOURCE_ID]]",
"type": "user"
}
}
""");
// Passes even if response contains additional fields
TimeProvider Integration
Deterministic Time Testing
The biggest challenge in testing time-sensitive code is dealing with DateTime.Now
and DateTime.UtcNow
. This library solves it:
// ❌ Flaky test - timing dependent
var response = await api.CreateOrderAsync(order);
var parsed = JsonSerializer.Deserialize<Order>(response);
Assert.True(parsed.CreatedAt > DateTime.UtcNow.AddSeconds(-5));
Assert.True(parsed.CreatedAt < DateTime.UtcNow.AddSeconds(5));
// ✅ Deterministic test with TimeProvider
var fixedTime = new FakeTimeProvider(new DateTimeOffset(2024, 1, 1, 10, 0, 0, TimeSpan.Zero));
response.AsJsonString()
.WithTimeProvider(fixedTime)
.Should()
.FullyMatch("""
{
"orderId": "[[ORDER_ID]]",
"createdAt": "{{UTCNOW()}}",
"expiresAt": "{{UTCNOW()}}"
}
""");
Time-Based Function Testing
Test different time formats and time zones consistently:
var testTime = new FakeTimeProvider(new DateTimeOffset(2024, 6, 15, 14, 30, 0, TimeSpan.FromHours(-5)));
apiResponse.AsJsonString()
.WithTimeProvider(testTime)
.Should()
.FullyMatch("""
{
"scheduledAt": "{{NOW()}}", // Local time with timezone
"createdUtc": "{{UTCNOW()}}", // UTC time
"sessionId": "{{GUID()}}" // Generated GUID
}
""");
Integration with System Clock
For production-like testing, use the system clock:
realApiResponse.AsJsonString()
.WithTimeProvider(TimeProvider.System)
.Should()
.FullyMatch("""
{
"timestamp": "{{UTCNOW()}}",
"data": { "status": "processed" }
}
""");
Advanced Features
Token Extraction for Multi-Step Tests
// Step 1: Create user and extract ID
var createResult = createUserResponse.AsJsonString()
.Should()
.FullyMatch("""{"userId": "[[USER_ID]]", "status": "created"}""");
var userId = createResult.ExtractedValues["USER_ID"];
// Step 2: Use extracted ID in subsequent test
var getUserResponse = await httpClient.GetAsync($"/users/{userId}");
getUserResponse.AsJsonString()
.Should()
.ContainSubset("""{"id": "[[SAME_USER_ID]]", "status": "active"}""");
Complex Nested Validation
complexApiResponse.AsJsonString().Should().FullyMatch("""
{
"metadata": {
"requestId": "{{GUID()}}",
"timestamp": "{{UTCNOW()}}",
"version": "1.0"
},
"data": {
"users": [
{
"id": "[[USER1_ID]]",
"profile": {
"createdAt": "{{UTCNOW()}}",
"settings": {
"theme": "dark",
"notifications": true
}
}
}
]
},
"pagination": {
"total": "[[TOTAL_COUNT]]",
"hasMore": false
}
}
""");
Installation
dotnet add package PQSoft.JsonComparer.AwesomeAssertions
Dependencies
This package depends on:
- PQSoft.JsonComparer
- AwesomeAssertions
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- AwesomeAssertions (>= 9.1.0)
- PQSoft.JsonComparer (>= 1.1.0-beta.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.1.0-beta.3 | 145 | 9/20/2025 |
1.1.0-beta.2 | 161 | 9/19/2025 |
1.1.0-beta.1 | 165 | 9/19/2025 |
1.0.0-beta.6 | 229 | 9/19/2025 |
1.0.0-beta.5 | 225 | 9/19/2025 |
1.0.0-beta.4 | 223 | 9/19/2025 |
1.0.0-beta.3 | 224 | 9/19/2025 |
1.0.0-beta.2 | 225 | 9/19/2025 |
1.0.0-beta.1 | 240 | 9/19/2025 |
1.0.0-alpha9 | 242 | 9/18/2025 |
1.0.0-alpha8 | 243 | 9/18/2025 |
1.0.0-alpha7 | 249 | 9/17/2025 |
1.0.0-alpha5 | 247 | 9/16/2025 |
1.0.0-alpha4 | 250 | 9/16/2025 |
1.0.0-alpha3 | 248 | 9/16/2025 |
1.0.0-alpha2 | 246 | 9/16/2025 |
1.0.0-alpha11 | 243 | 9/19/2025 |
1.0.0-alpha10 | 241 | 9/18/2025 |
1.0.0-alpha1 | 194 | 9/15/2025 |