@@ -16,87 +16,110 @@ public abstract class ApiTestBase<TResponse, TInterface, TDescriptor, TInitializ
16
16
where TInitializer : class , TInterface
17
17
where TInterface : class
18
18
{
19
- protected readonly IIntegrationCluster _cluster ;
19
+ private readonly EndpointUsage _usage ;
20
20
private readonly LazyResponses _responses ;
21
+ private readonly int _port ;
22
+ private readonly CallUniqueValues _uniqueValues ;
21
23
22
24
protected static string RandomString ( ) => Guid . NewGuid ( ) . ToString ( "N" ) . Substring ( 0 , 8 ) ;
23
- protected virtual ConnectionSettings GetConnectionSettings ( ConnectionSettings settings ) => settings ;
24
- protected virtual IElasticClient Client => this . _cluster . Client ( GetConnectionSettings ) ;
25
+ protected bool RanIntegrationSetup => this . _usage ? . CalledSetup ?? false ;
26
+
27
+ protected IIntegrationCluster Cluster { get ; }
25
28
26
- protected IDictionary < Integration . ClientMethod , string > UniqueValues { get ; }
27
- protected string CallIsolatedValue { get ; private set ; }
29
+ protected string CallIsolatedValue => _uniqueValues . Value ;
30
+ protected T ExtendedValue < T > ( string key ) where T : class => this . _uniqueValues . ExtendedValue < T > ( key ) ;
28
31
29
- protected virtual void BeforeAllCalls ( IElasticClient client , IDictionary < Integration . ClientMethod , string > values ) { }
32
+ protected virtual void IntegrationSetup ( IElasticClient client , CallUniqueValues values ) { }
30
33
protected virtual void OnBeforeCall ( IElasticClient client ) { }
31
34
protected virtual void OnAfterCall ( IElasticClient client ) { }
32
35
33
- protected virtual int Port { get ; set ; } = 9200 ;
36
+ protected IElasticClient Client => this . Cluster . Client ( GetConnectionSettings ) ;
37
+ protected virtual ConnectionSettings GetConnectionSettings ( ConnectionSettings settings ) => settings ;
34
38
35
- protected virtual TInitializer Initializer { get ; }
39
+ protected virtual TDescriptor NewDescriptor ( ) => Activator . CreateInstance < TDescriptor > ( ) ;
36
40
protected virtual Func < TDescriptor , TInterface > Fluent { get ; }
41
+ protected virtual TInitializer Initializer { get ; }
37
42
38
- protected virtual TDescriptor ClientDoesThisInternally ( TDescriptor d ) => d ;
39
43
protected abstract LazyResponses ClientUsage ( ) ;
40
44
41
- protected virtual TDescriptor NewDescriptor ( ) => Activator . CreateInstance < TDescriptor > ( ) ;
42
-
43
45
protected abstract string UrlPath { get ; }
44
46
protected abstract HttpMethod HttpMethod { get ; }
45
47
46
48
protected ApiTestBase ( IIntegrationCluster cluster , EndpointUsage usage )
47
49
{
48
- this . _cluster = cluster ;
50
+ this . _usage = usage ;
51
+ this . Cluster = cluster ;
52
+
49
53
this . _responses = usage . CallOnce ( this . ClientUsage ) ;
50
- this . Port = cluster . Node . Port ;
51
- this . UniqueValues = usage . CallUniqueValues ;
52
- this . CallIsolatedValue = UniqueValues [ Integration . ClientMethod . Fluent ] ;
54
+ this . _port = cluster . Node . Port ;
55
+ this . _uniqueValues = usage . CallUniqueValues ;
53
56
this . SetupSerialization ( ) ;
54
57
}
55
58
56
- protected virtual LazyResponses Calls (
59
+ [ U ] protected async Task HitsTheCorrectUrl ( ) =>
60
+ await this . AssertOnAllResponses ( r => this . AssertUrl ( r . ApiCall . Uri ) ) ;
61
+
62
+ [ U ] protected async Task UsesCorrectHttpMethod ( ) =>
63
+ await this . AssertOnAllResponses ( r => r . CallDetails . HttpMethod . Should ( ) . Be ( this . HttpMethod ) ) ;
64
+
65
+ [ U ] protected void SerializesInitializer ( ) =>
66
+ this . AssertSerializesAndRoundTrips < TInterface > ( this . Initializer ) ;
67
+
68
+ [ U ] protected void SerializesFluent ( ) =>
69
+ this . AssertSerializesAndRoundTrips ( this . Fluent ? . Invoke ( NewDescriptor ( ) ) ) ;
70
+
71
+ protected LazyResponses Calls (
57
72
Func < IElasticClient , Func < TDescriptor , TInterface > , TResponse > fluent ,
58
73
Func < IElasticClient , Func < TDescriptor , TInterface > , Task < TResponse > > fluentAsync ,
59
74
Func < IElasticClient , TInitializer , TResponse > request ,
60
75
Func < IElasticClient , TInitializer , Task < TResponse > > requestAsync
61
76
)
62
77
{
78
+ //this client is outside the lambda so that the callstack is one where we can get the method name
79
+ //of the current running test and send that as a header, great for e.g fiddler to relate requests with the test that sent it
63
80
var client = this . Client ;
64
81
return new LazyResponses ( async ( ) =>
65
82
{
66
- this . BeforeAllCalls ( client , UniqueValues ) ;
83
+ if ( TestClient . Configuration . RunIntegrationTests )
84
+ {
85
+ this . IntegrationSetup ( client , _uniqueValues ) ;
86
+ }
87
+
88
+ this . _usage . CalledSetup = true ;
67
89
68
90
var dict = new Dictionary < ClientMethod , IResponse > ( ) ;
69
- this . CallIsolatedValue = UniqueValues [ ClientMethod . Fluent ] ;
91
+ _uniqueValues . CurrentView = ClientMethod . Fluent ;
92
+
70
93
OnBeforeCall ( client ) ;
71
94
dict . Add ( ClientMethod . Fluent , fluent ( client , this . Fluent ) ) ;
72
95
OnAfterCall ( client ) ;
73
96
74
- this . CallIsolatedValue = UniqueValues [ ClientMethod . FluentAsync ] ;
97
+ _uniqueValues . CurrentView = ClientMethod . FluentAsync ;
75
98
OnBeforeCall ( client ) ;
76
99
dict . Add ( ClientMethod . FluentAsync , await fluentAsync ( client , this . Fluent ) ) ;
77
100
OnAfterCall ( client ) ;
78
101
79
- this . CallIsolatedValue = UniqueValues [ ClientMethod . Initializer ] ;
102
+ _uniqueValues . CurrentView = ClientMethod . Initializer ;
80
103
OnBeforeCall ( client ) ;
81
104
dict . Add ( ClientMethod . Initializer , request ( client , this . Initializer ) ) ;
82
105
OnAfterCall ( client ) ;
83
106
84
- this . CallIsolatedValue = UniqueValues [ ClientMethod . InitializerAsync ] ;
107
+ _uniqueValues . CurrentView = ClientMethod . InitializerAsync ;
85
108
OnBeforeCall ( client ) ;
86
109
dict . Add ( ClientMethod . InitializerAsync , await requestAsync ( client , this . Initializer ) ) ;
87
110
OnAfterCall ( client ) ;
88
111
return dict ;
89
112
} ) ;
90
113
}
91
114
92
- protected virtual void AssertUrl ( Uri u )
115
+ private void AssertUrl ( Uri u )
93
116
{
94
117
var paths = ( this . UrlPath ?? "" ) . Split ( new [ ] { '?' } , 2 ) ;
95
118
string path = paths . First ( ) , query = string . Empty ;
96
119
if ( paths . Length > 1 )
97
120
query = paths . Last ( ) ;
98
121
99
- var expectedUri = new UriBuilder ( "http" , "localhost" , Port , path , "?" + query ) . Uri ;
122
+ var expectedUri = new UriBuilder ( "http" , "localhost" , this . _port , path , "?" + query ) . Uri ;
100
123
101
124
u . AbsolutePath . Should ( ) . Be ( expectedUri . AbsolutePath ) ;
102
125
u = new UriBuilder ( u . Scheme , u . Host , u . Port , u . AbsolutePath , u . Query . Replace ( "pretty=true&" , "" ) . Replace ( "pretty=true" , "" ) ) . Uri ;
@@ -131,7 +154,7 @@ protected virtual async Task AssertOnAllResponses(Action<TResponse> assert)
131
154
var response = kv . Value as TResponse ;
132
155
try
133
156
{
134
- this . CallIsolatedValue = UniqueValues [ kv . Key ] ;
157
+ this . _uniqueValues . CurrentView = kv . Key ;
135
158
assert ( response ) ;
136
159
}
137
160
#pragma warning disable 7095 //enable this if you expect a single overload to act up
@@ -143,16 +166,5 @@ protected virtual async Task AssertOnAllResponses(Action<TResponse> assert)
143
166
}
144
167
}
145
168
146
- [ U ] protected async Task HitsTheCorrectUrl ( ) =>
147
- await this . AssertOnAllResponses ( r => this . AssertUrl ( r . ApiCall . Uri ) ) ;
148
-
149
- [ U ] protected async Task UsesCorrectHttpMethod ( ) =>
150
- await this . AssertOnAllResponses ( r => r . CallDetails . HttpMethod . Should ( ) . Be ( this . HttpMethod ) ) ;
151
-
152
- [ U ] protected void SerializesInitializer ( ) =>
153
- this . AssertSerializesAndRoundTrips < TInterface > ( this . Initializer ) ;
154
-
155
- [ U ] protected void SerializesFluent ( ) =>
156
- this . AssertSerializesAndRoundTrips ( this . Fluent ? . Invoke ( this . ClientDoesThisInternally ( NewDescriptor ( ) ) ) ) ;
157
169
}
158
170
}
0 commit comments