Skip to content

Commit 1af1def

Browse files
committed
[DEVEX-222] Added SchemaRegistry tests
1 parent 9acba54 commit 1af1def

File tree

2 files changed

+326
-0
lines changed

2 files changed

+326
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using EventStore.Client;
2+
using Kurrent.Client.Core.Serialization;
3+
4+
namespace Kurrent.Client.Tests.Core.Serialization;
5+
6+
using static Constants.Metadata.ContentTypes;
7+
8+
public class ContentTypeExtensionsTests {
9+
[Fact]
10+
public void FromMessageContentType_WithApplicationJson_ReturnsJsonContentType() {
11+
// Given
12+
// When
13+
var result = ContentTypeExtensions.FromMessageContentType(ApplicationJson);
14+
15+
// Then
16+
Assert.Equal(ContentType.Json, result);
17+
}
18+
19+
[Fact]
20+
public void FromMessageContentType_WithAnyOtherContentType_ReturnsBytesContentType() {
21+
// Given
22+
// When
23+
var result = ContentTypeExtensions.FromMessageContentType(ApplicationOctetStream);
24+
25+
// Then
26+
Assert.Equal(ContentType.Bytes, result);
27+
}
28+
29+
[Fact]
30+
public void FromMessageContentType_WithRandomString_ReturnsBytesContentType() {
31+
// Given
32+
const string contentType = "some-random-content-type";
33+
34+
// When
35+
var result = ContentTypeExtensions.FromMessageContentType(contentType);
36+
37+
// Then
38+
Assert.Equal(ContentType.Bytes, result);
39+
}
40+
41+
[Fact]
42+
public void ToMessageContentType_WithJsonContentType_ReturnsApplicationJson() {
43+
// Given
44+
// When
45+
var result = ContentType.Json.ToMessageContentType();
46+
47+
// Then
48+
Assert.Equal(ApplicationJson, result);
49+
}
50+
51+
[Fact]
52+
public void ToMessageContentType_WithBytesContentType_ReturnsApplicationOctetStream() {
53+
// Given
54+
// When
55+
var result = ContentType.Bytes.ToMessageContentType();
56+
57+
// Then
58+
Assert.Equal(ApplicationOctetStream, result);
59+
}
60+
61+
[Fact]
62+
public void ToMessageContentType_WithInvalidContentType_ThrowsArgumentOutOfRangeException() {
63+
// Given
64+
var contentType = (ContentType)999; // Invalid content type
65+
66+
// When/Then
67+
Assert.Throws<ArgumentOutOfRangeException>(() => contentType.ToMessageContentType());
68+
}
69+
}
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using System.Text.Json;
3+
using EventStore.Client;
4+
using Kurrent.Client.Core.Serialization;
5+
6+
namespace Kurrent.Client.Tests.Core.Serialization;
7+
8+
public class SchemaRegistryTests {
9+
// Test classes
10+
record TestEvent1;
11+
12+
record TestEvent2;
13+
14+
record TestEvent3;
15+
16+
record TestMetadata;
17+
18+
[Fact]
19+
public void Constructor_InitializesProperties() {
20+
// Given
21+
var serializers = new Dictionary<ContentType, ISerializer> {
22+
{ ContentType.Json, new SystemTextJsonSerializer() },
23+
{ ContentType.Bytes, new SystemTextJsonSerializer() }
24+
};
25+
26+
var namingStrategy = new DefaultMessageTypeNamingStrategy(typeof(TestMetadata));
27+
28+
// When
29+
var registry = new SchemaRegistry(serializers, namingStrategy);
30+
31+
// Then
32+
Assert.Same(namingStrategy, registry.MessageTypeNamingStrategy);
33+
}
34+
35+
[Fact]
36+
public void GetSerializer_ReturnsCorrectSerializer() {
37+
// Given
38+
var jsonSerializer = new SystemTextJsonSerializer();
39+
var bytesSerializer = new SystemTextJsonSerializer();
40+
41+
var serializers = new Dictionary<ContentType, ISerializer> {
42+
{ ContentType.Json, jsonSerializer },
43+
{ ContentType.Bytes, bytesSerializer }
44+
};
45+
46+
var registry = new SchemaRegistry(
47+
serializers,
48+
new DefaultMessageTypeNamingStrategy(typeof(TestMetadata))
49+
);
50+
51+
// When
52+
var resultJsonSerializer = registry.GetSerializer(ContentType.Json);
53+
var resultBytesSerializer = registry.GetSerializer(ContentType.Bytes);
54+
55+
// Then
56+
Assert.NotSame(resultJsonSerializer, resultBytesSerializer);
57+
Assert.Same(jsonSerializer, resultJsonSerializer);
58+
Assert.Same(bytesSerializer, resultBytesSerializer);
59+
}
60+
61+
[Fact]
62+
public void From_WithDefaultSettings_CreatesRegistryWithDefaults() {
63+
// Given
64+
var settings = new KurrentClientSerializationSettings();
65+
66+
// When
67+
var registry = SchemaRegistry.From(settings);
68+
69+
// Then
70+
Assert.NotNull(registry);
71+
Assert.NotNull(registry.MessageTypeNamingStrategy);
72+
Assert.NotNull(registry.GetSerializer(ContentType.Json));
73+
Assert.NotNull(registry.GetSerializer(ContentType.Bytes));
74+
75+
Assert.IsType<MessageTypeNamingStrategyWrapper>(registry.MessageTypeNamingStrategy);
76+
Assert.IsType<SystemTextJsonSerializer>(registry.GetSerializer(ContentType.Json));
77+
Assert.IsType<SystemTextJsonSerializer>(registry.GetSerializer(ContentType.Bytes));
78+
}
79+
80+
[Fact]
81+
public void From_WithCustomJsonSerializer_UsesProvidedSerializer() {
82+
// Given
83+
var customJsonSerializer = new SystemTextJsonSerializer(
84+
new SystemTextJsonSerializationSettings {
85+
Options = new JsonSerializerOptions { WriteIndented = true }
86+
}
87+
);
88+
89+
var settings = new KurrentClientSerializationSettings()
90+
.UseJsonSerializer(customJsonSerializer);
91+
92+
// When
93+
var registry = SchemaRegistry.From(settings);
94+
95+
// Then
96+
Assert.Same(customJsonSerializer, registry.GetSerializer(ContentType.Json));
97+
Assert.NotSame(customJsonSerializer, registry.GetSerializer(ContentType.Bytes));
98+
}
99+
100+
[Fact]
101+
public void From_WithCustomBytesSerializer_UsesProvidedSerializer() {
102+
// Given
103+
var customBytesSerializer = new SystemTextJsonSerializer(
104+
new SystemTextJsonSerializationSettings {
105+
Options = new JsonSerializerOptions { WriteIndented = true }
106+
}
107+
);
108+
109+
var settings = new KurrentClientSerializationSettings()
110+
.UseBytesSerializer(customBytesSerializer);
111+
112+
// When
113+
var registry = SchemaRegistry.From(settings);
114+
115+
// Then
116+
Assert.Same(customBytesSerializer, registry.GetSerializer(ContentType.Bytes));
117+
Assert.NotSame(customBytesSerializer, registry.GetSerializer(ContentType.Json));
118+
}
119+
120+
[Fact]
121+
public void From_WithMessageTypeMap_RegistersTypes() {
122+
// Given
123+
var settings = new KurrentClientSerializationSettings();
124+
settings.RegisterMessageType<TestEvent1>("test-event-1");
125+
settings.RegisterMessageType<TestEvent2>("test-event-2");
126+
127+
// When
128+
var registry = SchemaRegistry.From(settings);
129+
var namingStrategy = registry.MessageTypeNamingStrategy;
130+
131+
// Then
132+
// Verify types can be resolved
133+
Assert.True(namingStrategy.TryResolveClrType("test-event-1", out var type1));
134+
Assert.Equal(typeof(TestEvent1), type1);
135+
136+
Assert.True(namingStrategy.TryResolveClrType("test-event-2", out var type2));
137+
Assert.Equal(typeof(TestEvent2), type2);
138+
}
139+
140+
[Fact]
141+
public void From_WithCategoryMessageTypesMap_RegistersTypesWithCategories() {
142+
// Given
143+
var settings = new KurrentClientSerializationSettings();
144+
settings.RegisterMessageTypeForCategory<TestEvent1>("category1");
145+
settings.RegisterMessageTypeForCategory<TestEvent2>("category1");
146+
settings.RegisterMessageTypeForCategory<TestEvent3>("category2");
147+
148+
// When
149+
var registry = SchemaRegistry.From(settings);
150+
var namingStrategy = registry.MessageTypeNamingStrategy;
151+
152+
// Then
153+
// For categories, the naming strategy should have resolved the type names
154+
// using the ResolveTypeName method, which by default uses the type's name
155+
string typeName1 = namingStrategy.ResolveTypeName(
156+
typeof(TestEvent1),
157+
new MessageTypeNamingResolutionContext("category1")
158+
);
159+
160+
string typeName2 = namingStrategy.ResolveTypeName(
161+
typeof(TestEvent2),
162+
new MessageTypeNamingResolutionContext("category1")
163+
);
164+
165+
string typeName3 = namingStrategy.ResolveTypeName(
166+
typeof(TestEvent3),
167+
new MessageTypeNamingResolutionContext("category2")
168+
);
169+
170+
// Verify types can be resolved by the type names
171+
Assert.True(namingStrategy.TryResolveClrType(typeName1, out var resolvedType1));
172+
Assert.Equal(typeof(TestEvent1), resolvedType1);
173+
174+
Assert.True(namingStrategy.TryResolveClrType(typeName2, out var resolvedType2));
175+
Assert.Equal(typeof(TestEvent2), resolvedType2);
176+
177+
Assert.True(namingStrategy.TryResolveClrType(typeName3, out var resolvedType3));
178+
Assert.Equal(typeof(TestEvent3), resolvedType3);
179+
}
180+
181+
[Fact]
182+
public void From_WithCustomNamingStrategy_UsesProvidedStrategy() {
183+
// Given
184+
var customNamingStrategy = new TestNamingStrategy();
185+
var settings = new KurrentClientSerializationSettings()
186+
.UseMessageTypeNamingStrategy(customNamingStrategy);
187+
188+
// When
189+
var registry = SchemaRegistry.From(settings);
190+
191+
// Then
192+
// The registry wraps the naming strategy, but should still use it
193+
var wrappedStrategy = registry.MessageTypeNamingStrategy;
194+
Assert.IsType<MessageTypeNamingStrategyWrapper>(wrappedStrategy);
195+
196+
// Test to make sure it behaves like our custom strategy
197+
string typeName = wrappedStrategy.ResolveTypeName(
198+
typeof(TestEvent1),
199+
new MessageTypeNamingResolutionContext("test")
200+
);
201+
202+
// Our test strategy adds "Custom-" prefix
203+
Assert.StartsWith("Custom-", typeName);
204+
}
205+
206+
[Fact]
207+
public void From_WithNoMessageTypeNamingStrategy_UsesDefaultStrategy() {
208+
// Given
209+
var settings = new KurrentClientSerializationSettings {
210+
MessageTypeNamingStrategy = null,
211+
DefaultMetadataType = typeof(TestMetadata)
212+
};
213+
214+
// When
215+
var registry = SchemaRegistry.From(settings);
216+
217+
// Then
218+
Assert.NotNull(registry.MessageTypeNamingStrategy);
219+
220+
// The wrapped default strategy should use our metadata type
221+
Assert.True(
222+
registry.MessageTypeNamingStrategy.TryResolveClrMetadataType("some-type", out var defaultMetadataType)
223+
);
224+
225+
Assert.Equal(typeof(TestMetadata), defaultMetadataType);
226+
}
227+
228+
// Custom naming strategy for testing
229+
class TestNamingStrategy : IMessageTypeNamingStrategy {
230+
public string ResolveTypeName(Type type, MessageTypeNamingResolutionContext context) {
231+
return $"Custom-{type.Name}-{context.CategoryName}";
232+
}
233+
#if NET48
234+
public bool TryResolveClrType(string messageTypeName, out Type? clrType)
235+
#else
236+
public bool TryResolveClrType(string messageTypeName, [NotNullWhen(true)] out Type? clrType)
237+
#endif
238+
{
239+
// Simple implementation for testing
240+
clrType = messageTypeName.StartsWith("Custom-TestEvent1")
241+
? typeof(TestEvent1)
242+
: null;
243+
244+
return clrType != null;
245+
}
246+
247+
#if NET48
248+
public bool TryResolveClrMetadataType(string messageTypeName, out Type? clrType)
249+
#else
250+
public bool TryResolveClrMetadataType(string messageTypeName, [NotNullWhen(true)] out Type? clrType)
251+
#endif
252+
{
253+
clrType = typeof(TestMetadata);
254+
return true;
255+
}
256+
}
257+
}

0 commit comments

Comments
 (0)