11#nullable enable
2+ using Sentry . Extensions . AI ;
23
34namespace Sentry . Extensions . AI . Tests ;
45
56public class SentryAIActivityListenerTests
67{
7- private IHub Hub { get ; }
8- private ActivitySource SentryActivitySource { get ; }
9- private ISpan Span { get ; }
10-
11- public SentryAIActivityListenerTests ( )
8+ private class Fixture
129 {
13- Hub = Substitute . For < IHub > ( ) ;
14- SentryActivitySource = SentryAIActivitySource . Instance ;
15- Span = Substitute . For < ISpan > ( ) ;
16- SentrySdk . UseHub ( Hub ) ;
10+ private SentryOptions Options { get ; }
11+ public ISentryClient Client { get ; }
12+ public IHub Hub { get ; set ; }
13+
14+ public Fixture ( )
15+ {
16+ Options = new SentryOptions
17+ {
18+ Dsn = ValidDsn ,
19+ TracesSampleRate = 1.0 ,
20+ } ;
21+
22+ Hub = Substitute . For < IHub > ( ) ;
23+ Client = Substitute . For < ISentryClient > ( ) ;
24+ SentrySdk . Init ( Options ) ;
25+ }
1726 }
1827
28+ private readonly Fixture _fixture = new ( ) ;
29+
1930 [ Fact ]
2031 public void Init_AddsActivityListenerToActivitySource ( )
2132 {
2233 // Act
2334 SentryAIActivityListener . Init ( ) ;
2435
2536 // Assert
26- Assert . True ( SentryActivitySource . HasListeners ( ) ) ;
37+ Assert . True ( SentryAIActivitySource . Instance . HasListeners ( ) ) ;
2738 }
2839
2940 [ Theory ]
@@ -62,7 +73,7 @@ public void Sample_ReturnsAllDataAndRecordedForFICCActivityNames(string activity
6273 SentryAIActivityListener . Init ( ) ;
6374
6475 // Act
65- using var activity = SentryActivitySource . StartActivity ( activityName ) ;
76+ using var activity = SentryAIActivitySource . Instance . StartActivity ( activityName ) ;
6677
6778 // Assert
6879 Assert . NotNull ( activity ) ;
@@ -80,7 +91,7 @@ public void Sample_ReturnsNoneForNonFICCActivityNames(string activityName)
8091 SentryAIActivityListener . Init ( ) ;
8192
8293 // Act
83- using var activity = SentryActivitySource . StartActivity ( activityName ) ;
94+ using var activity = SentryAIActivitySource . Instance . StartActivity ( activityName ) ;
8495
8596 // Assert
8697 // For non-FICC activity names, the activity may still be created but not recorded
@@ -89,4 +100,36 @@ public void Sample_ReturnsNoneForNonFICCActivityNames(string activityName)
89100 Assert . False ( activity . Recorded ) ;
90101 }
91102 }
103+
104+ [ Fact ]
105+ public void Init_MultipleCalls_NoDuplicateListener_StartsOnlyOneTransaction ( )
106+ {
107+ // Arrange
108+ var sent = 0 ;
109+ using var _ = SentrySdk . Init ( o =>
110+ {
111+ o . Dsn = ValidDsn ;
112+ o . TracesSampleRate = 1.0 ;
113+ // Count transactions just before they are sent:
114+ o . SetBeforeSendTransaction ( t =>
115+ {
116+ Interlocked . Increment ( ref sent ) ;
117+ return t ;
118+ } ) ;
119+ } ) ;
120+
121+ // Act
122+ SentryAIActivityListener . Init ( ) ;
123+ SentryAIActivityListener . Init ( ) ;
124+ SentryAIActivityListener . Init ( ) ;
125+
126+ var activity = SentryAIActivitySource . Instance . StartActivity ( SentryAIConstants . FICCActivityNames [ 0 ] ) ;
127+
128+ // Assert
129+ Assert . NotNull ( activity ) ;
130+ Assert . True ( SentryAIActivitySource . Instance . HasListeners ( ) ) ;
131+ activity . Stop ( ) ;
132+
133+ Assert . Equal ( 1 , Volatile . Read ( ref sent ) ) ;
134+ }
92135}
0 commit comments