Skip to content

Commit 7d93657

Browse files
committed
Change SentryInstrumentedFunctionTests to use hub substitute
1 parent a2a89b3 commit 7d93657

File tree

1 file changed

+59
-33
lines changed

1 file changed

+59
-33
lines changed

test/Sentry.Extensions.AI.Tests/SentryInstrumentedFunctionTests.cs

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,24 @@ namespace Sentry.Extensions.AI.Tests;
55

66
public class SentryInstrumentedFunctionTests
77
{
8+
private class Fixture
9+
{
10+
public IHub Hub { get; } = Substitute.For<IHub>();
11+
12+
public Fixture()
13+
{
14+
Hub.IsEnabled.Returns(true);
15+
}
16+
}
17+
18+
private readonly Fixture _fixture = new();
19+
820
[Fact]
921
public async Task InvokeCoreAsync_WithValidFunction_ReturnsResult()
1022
{
1123
// Arrange
12-
using var sentryDisposable = SentryHelpers.InitializeSdk();
1324
var testFunction = AIFunctionFactory.Create(() => "test result", "TestFunction", "Test function description");
14-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
25+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
1526
var arguments = new AIFunctionArguments();
1627

1728
// Act
@@ -28,17 +39,20 @@ public async Task InvokeCoreAsync_WithValidFunction_ReturnsResult()
2839
{
2940
Assert.Equal("test result", result);
3041
}
42+
3143
Assert.Equal("TestFunction", sentryFunction.Name);
3244
Assert.Equal("Test function description", sentryFunction.Description);
45+
_fixture.Hub.Received(1).StartTransaction(
46+
Arg.Any<ITransactionContext>(),
47+
Arg.Any<IReadOnlyDictionary<string, object?>>());
3348
}
3449

3550
[Fact]
3651
public async Task InvokeCoreAsync_WithNullResult_ReturnsNull()
3752
{
3853
// Arrange
39-
using var sentryDisposable = SentryHelpers.InitializeSdk();
4054
var testFunction = AIFunctionFactory.Create(object? () => null, "TestFunction", "Test function description");
41-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
55+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
4256
var arguments = new AIFunctionArguments();
4357

4458
// Act
@@ -53,16 +67,19 @@ public async Task InvokeCoreAsync_WithNullResult_ReturnsNull()
5367
{
5468
Assert.Null(result);
5569
}
70+
71+
_fixture.Hub.Received(1).StartTransaction(
72+
Arg.Any<ITransactionContext>(),
73+
Arg.Any<IReadOnlyDictionary<string, object?>>());
5674
}
5775

5876
[Fact]
5977
public async Task InvokeCoreAsync_WithJsonNullResult_ReturnsJsonElement()
6078
{
6179
// Arrange
62-
using var sentryDisposable = SentryHelpers.InitializeSdk();
6380
var jsonNullElement = JsonSerializer.Deserialize<JsonElement>("null");
6481
var testFunction = AIFunctionFactory.Create(() => jsonNullElement, "TestFunction", "Test function description");
65-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
82+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
6683
var arguments = new AIFunctionArguments();
6784

6885
// Act
@@ -73,16 +90,18 @@ public async Task InvokeCoreAsync_WithJsonNullResult_ReturnsJsonElement()
7390
Assert.IsType<JsonElement>(result);
7491
var jsonResult = (JsonElement)result;
7592
Assert.Equal(JsonValueKind.Null, jsonResult.ValueKind);
93+
_fixture.Hub.Received(1).StartTransaction(
94+
Arg.Any<ITransactionContext>(),
95+
Arg.Any<IReadOnlyDictionary<string, object?>>());
7696
}
7797

7898
[Fact]
7999
public async Task InvokeCoreAsync_WithJsonElementResult_CallsToStringForSpanOutput()
80100
{
81101
// Arrange
82-
using var sentryDisposable = SentryHelpers.InitializeSdk();
83102
var jsonElement = JsonSerializer.Deserialize<JsonElement>("\"test output\"");
84103
var testFunction = AIFunctionFactory.Create(() => jsonElement, "TestFunction", "Test function description");
85-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
104+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
86105
var arguments = new AIFunctionArguments();
87106

88107
// Act
@@ -93,16 +112,22 @@ public async Task InvokeCoreAsync_WithJsonElementResult_CallsToStringForSpanOutp
93112
Assert.IsType<JsonElement>(result);
94113
var jsonResult = (JsonElement)result;
95114
Assert.Equal("test output", jsonResult.GetString());
115+
_fixture.Hub.Received(1).StartTransaction(
116+
Arg.Any<ITransactionContext>(),
117+
Arg.Any<IReadOnlyDictionary<string, object?>>());
96118
}
97119

98120
[Fact]
99121
public async Task InvokeCoreAsync_WithComplexResult_ReturnsObject()
100122
{
101123
// Arrange
102-
using var sentryDisposable = SentryHelpers.InitializeSdk();
103-
var resultObject = new { message = "test", count = 42 };
124+
var resultObject = new
125+
{
126+
message = "test",
127+
count = 42
128+
};
104129
var testFunction = AIFunctionFactory.Create(() => resultObject, "TestFunction", "Test function description");
105-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
130+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
106131
var arguments = new AIFunctionArguments();
107132

108133
// Act
@@ -122,67 +147,81 @@ public async Task InvokeCoreAsync_WithComplexResult_ReturnsObject()
122147
{
123148
Assert.Equal(resultObject, result);
124149
}
150+
151+
_fixture.Hub.Received(1).StartTransaction(
152+
Arg.Any<ITransactionContext>(),
153+
Arg.Any<IReadOnlyDictionary<string, object?>>());
125154
}
126155

127156
[Fact]
128157
public async Task InvokeCoreAsync_WhenFunctionThrows_PropagatesException()
129158
{
130159
// Arrange
131-
using var sentryDisposable = SentryHelpers.InitializeSdk();
132160
var expectedException = new InvalidOperationException("Test exception");
133-
var testFunction = AIFunctionFactory.Create(new Func<object>(() => throw expectedException), "TestFunction", "Test function description");
134-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
161+
var testFunction = AIFunctionFactory.Create(new Func<object>(() => throw expectedException), "TestFunction",
162+
"Test function description");
163+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
135164
var arguments = new AIFunctionArguments();
136165

137166
// Act & Assert
138167
var actualException = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
139168
await sentryFunction.InvokeAsync(arguments));
140169

141170
Assert.Equal(expectedException.Message, actualException.Message);
171+
_fixture.Hub.Received(1).StartTransaction(
172+
Arg.Any<ITransactionContext>(),
173+
Arg.Any<IReadOnlyDictionary<string, object?>>());
142174
}
143175

144176
[Fact]
145177
public async Task InvokeCoreAsync_WithCancellation_PropagatesCancellation()
146178
{
147179
// Arrange
148-
using var sentryDisposable = SentryHelpers.InitializeSdk();
149180
var testFunction = AIFunctionFactory.Create((CancellationToken cancellationToken) =>
150181
{
151182
cancellationToken.ThrowIfCancellationRequested();
152183
return "result";
153184
}, "TestFunction", "Test function description");
154185

155-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
186+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
156187
var arguments = new AIFunctionArguments();
157188
var cts = new CancellationTokenSource();
158189
await cts.CancelAsync();
159190

160191
// Act & Assert
161192
await Assert.ThrowsAsync<OperationCanceledException>(async () =>
162193
await sentryFunction.InvokeAsync(arguments, cts.Token));
194+
_fixture.Hub.Received(1).StartTransaction(
195+
Arg.Any<ITransactionContext>(),
196+
Arg.Any<IReadOnlyDictionary<string, object?>>());
163197
}
164198

165199
[Fact]
166200
public async Task InvokeCoreAsync_WithParameters_PassesParametersCorrectly()
167201
{
168202
// Arrange
169-
using var sentryDisposable = SentryHelpers.InitializeSdk();
170203
var receivedArguments = (AIFunctionArguments?)null;
171204
var testFunction = AIFunctionFactory.Create((AIFunctionArguments args) =>
172205
{
173206
receivedArguments = args;
174207
return "result";
175208
}, "TestFunction", "Test function description");
176209

177-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
178-
var arguments = new AIFunctionArguments { ["param1"] = "value1" };
210+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
211+
var arguments = new AIFunctionArguments
212+
{
213+
["param1"] = "value1"
214+
};
179215

180216
// Act
181217
await sentryFunction.InvokeAsync(arguments);
182218

183219
// Assert
184220
Assert.NotNull(receivedArguments);
185221
Assert.Equal("value1", receivedArguments["param1"]);
222+
_fixture.Hub.Received(1).StartTransaction(
223+
Arg.Any<ITransactionContext>(),
224+
Arg.Any<IReadOnlyDictionary<string, object?>>());
186225
}
187226

188227
[Fact]
@@ -192,23 +231,10 @@ public void Constructor_PreservesInnerFunctionProperties()
192231
var testFunction = AIFunctionFactory.Create(() => "test", "TestFunction", "Test function description");
193232

194233
// Act
195-
var sentryFunction = new SentryInstrumentedFunction(testFunction);
234+
var sentryFunction = new SentryInstrumentedFunction(testFunction, _fixture.Hub);
196235

197236
// Assert
198237
Assert.Equal("TestFunction", sentryFunction.Name);
199238
Assert.Equal("Test function description", sentryFunction.Description);
200239
}
201240
}
202-
203-
internal static class SentryHelpers
204-
{
205-
public static IDisposable InitializeSdk()
206-
{
207-
return SentrySdk.Init(options =>
208-
{
209-
options.Dsn = ValidDsn;
210-
options.TracesSampleRate = 1.0;
211-
options.Debug = false;
212-
});
213-
}
214-
}

0 commit comments

Comments
 (0)