1
- using System ;
2
- using System . Collections . Generic ;
3
- using System . Net . Http ;
4
- using System . Net . Http . Headers ;
5
- using System . Threading . Tasks ;
6
- using JsonApiDotNetCore . Middleware ;
7
1
using JsonApiDotNetCoreExample ;
8
- using Microsoft . AspNetCore . Hosting ;
9
- using Microsoft . AspNetCore . Mvc . Testing ;
10
2
using Microsoft . EntityFrameworkCore ;
11
- using Microsoft . Extensions . DependencyInjection ;
12
- using Microsoft . Extensions . Hosting ;
13
- using Microsoft . Extensions . Logging ;
14
- using Newtonsoft . Json ;
15
3
16
4
namespace JsonApiDotNetCoreExampleTests
17
5
{
@@ -23,225 +11,9 @@ namespace JsonApiDotNetCoreExampleTests
23
11
/// </summary>
24
12
/// <typeparam name="TStartup">The server Startup class, which can be defined in the test project.</typeparam>
25
13
/// <typeparam name="TDbContext">The EF Core database context, which can be defined in the test project.</typeparam>
26
- public class IntegrationTestContext < TStartup , TDbContext > : IDisposable
14
+ public class IntegrationTestContext < TStartup , TDbContext > : BaseIntegrationTestContext < TStartup , EmptyStartup , TDbContext >
27
15
where TStartup : class
28
16
where TDbContext : DbContext
29
17
{
30
- private readonly Lazy < WebApplicationFactory < EmptyStartup > > _lazyFactory ;
31
- private Action < ILoggingBuilder > _loggingConfiguration ;
32
- private Action < IServiceCollection > _beforeServicesConfiguration ;
33
- private Action < IServiceCollection > _afterServicesConfiguration ;
34
-
35
- public WebApplicationFactory < EmptyStartup > Factory => _lazyFactory . Value ;
36
-
37
- public IntegrationTestContext ( )
38
- {
39
- _lazyFactory = new Lazy < WebApplicationFactory < EmptyStartup > > ( CreateFactory ) ;
40
- }
41
-
42
- private WebApplicationFactory < EmptyStartup > CreateFactory ( )
43
- {
44
- string postgresPassword = Environment . GetEnvironmentVariable ( "PGPASSWORD" ) ?? "postgres" ;
45
- string dbConnectionString =
46
- $ "Host=localhost;Port=5432;Database=JsonApiTest-{ Guid . NewGuid ( ) : N} ;User ID=postgres;Password={ postgresPassword } ";
47
-
48
- var factory = new IntegrationTestWebApplicationFactory ( ) ;
49
-
50
- factory . ConfigureLogging ( _loggingConfiguration ) ;
51
-
52
- factory . ConfigureServicesBeforeStartup ( services =>
53
- {
54
- _beforeServicesConfiguration ? . Invoke ( services ) ;
55
-
56
- services . AddDbContext < TDbContext > ( options =>
57
- {
58
- options . UseNpgsql ( dbConnectionString ,
59
- postgresOptions => postgresOptions . SetPostgresVersion ( new Version ( 9 , 6 ) ) ) ;
60
-
61
- options . EnableSensitiveDataLogging ( ) ;
62
- options . EnableDetailedErrors ( ) ;
63
- } ) ;
64
- } ) ;
65
-
66
- factory . ConfigureServicesAfterStartup ( _afterServicesConfiguration ) ;
67
-
68
- using IServiceScope scope = factory . Services . CreateScope ( ) ;
69
- var dbContext = scope . ServiceProvider . GetRequiredService < TDbContext > ( ) ;
70
- dbContext . Database . EnsureCreated ( ) ;
71
-
72
- return factory ;
73
- }
74
-
75
- public void Dispose ( )
76
- {
77
- RunOnDatabaseAsync ( async context => await context . Database . EnsureDeletedAsync ( ) ) . Wait ( ) ;
78
-
79
- Factory . Dispose ( ) ;
80
- }
81
-
82
- public void ConfigureLogging ( Action < ILoggingBuilder > loggingConfiguration )
83
- {
84
- _loggingConfiguration = loggingConfiguration ;
85
- }
86
-
87
- public void ConfigureServicesBeforeStartup ( Action < IServiceCollection > servicesConfiguration )
88
- {
89
- _beforeServicesConfiguration = servicesConfiguration ;
90
- }
91
-
92
- public void ConfigureServicesAfterStartup ( Action < IServiceCollection > servicesConfiguration )
93
- {
94
- _afterServicesConfiguration = servicesConfiguration ;
95
- }
96
-
97
- public async Task RunOnDatabaseAsync ( Func < TDbContext , Task > asyncAction )
98
- {
99
- using IServiceScope scope = Factory . Services . CreateScope ( ) ;
100
- var dbContext = scope . ServiceProvider . GetRequiredService < TDbContext > ( ) ;
101
-
102
- await asyncAction ( dbContext ) ;
103
- }
104
-
105
- public async Task < ( HttpResponseMessage httpResponse , TResponseDocument responseDocument ) >
106
- ExecuteGetAsync < TResponseDocument > ( string requestUrl ,
107
- IEnumerable < MediaTypeWithQualityHeaderValue > acceptHeaders = null )
108
- {
109
- return await ExecuteRequestAsync < TResponseDocument > ( HttpMethod . Get , requestUrl , null , null , acceptHeaders ) ;
110
- }
111
-
112
- public async Task < ( HttpResponseMessage httpResponse , TResponseDocument responseDocument ) >
113
- ExecutePostAsync < TResponseDocument > ( string requestUrl , object requestBody ,
114
- string contentType = HeaderConstants . MediaType ,
115
- IEnumerable < MediaTypeWithQualityHeaderValue > acceptHeaders = null )
116
- {
117
- return await ExecuteRequestAsync < TResponseDocument > ( HttpMethod . Post , requestUrl , requestBody , contentType ,
118
- acceptHeaders ) ;
119
- }
120
-
121
- public async Task < ( HttpResponseMessage httpResponse , TResponseDocument responseDocument ) >
122
- ExecutePatchAsync < TResponseDocument > ( string requestUrl , object requestBody ,
123
- string contentType = HeaderConstants . MediaType ,
124
- IEnumerable < MediaTypeWithQualityHeaderValue > acceptHeaders = null )
125
- {
126
- return await ExecuteRequestAsync < TResponseDocument > ( HttpMethod . Patch , requestUrl , requestBody , contentType ,
127
- acceptHeaders ) ;
128
- }
129
-
130
- public async Task < ( HttpResponseMessage httpResponse , TResponseDocument responseDocument ) >
131
- ExecuteDeleteAsync < TResponseDocument > ( string requestUrl , object requestBody = null ,
132
- string contentType = HeaderConstants . MediaType ,
133
- IEnumerable < MediaTypeWithQualityHeaderValue > acceptHeaders = null )
134
- {
135
- return await ExecuteRequestAsync < TResponseDocument > ( HttpMethod . Delete , requestUrl , requestBody , contentType ,
136
- acceptHeaders ) ;
137
- }
138
-
139
- private async Task < ( HttpResponseMessage httpResponse , TResponseDocument responseDocument ) >
140
- ExecuteRequestAsync < TResponseDocument > ( HttpMethod method , string requestUrl , object requestBody ,
141
- string contentType , IEnumerable < MediaTypeWithQualityHeaderValue > acceptHeaders )
142
- {
143
- var request = new HttpRequestMessage ( method , requestUrl ) ;
144
- string requestText = SerializeRequest ( requestBody ) ;
145
-
146
- if ( ! string . IsNullOrEmpty ( requestText ) )
147
- {
148
- request . Content = new StringContent ( requestText ) ;
149
-
150
- if ( contentType != null )
151
- {
152
- request . Content . Headers . ContentType = MediaTypeHeaderValue . Parse ( contentType ) ;
153
- }
154
- }
155
-
156
- using HttpClient client = Factory . CreateClient ( ) ;
157
-
158
- if ( acceptHeaders != null )
159
- {
160
- foreach ( var acceptHeader in acceptHeaders )
161
- {
162
- client . DefaultRequestHeaders . Accept . Add ( acceptHeader ) ;
163
- }
164
- }
165
-
166
- HttpResponseMessage responseMessage = await client . SendAsync ( request ) ;
167
-
168
- string responseText = await responseMessage . Content . ReadAsStringAsync ( ) ;
169
- var responseDocument = DeserializeResponse < TResponseDocument > ( responseText ) ;
170
-
171
- return ( responseMessage , responseDocument ) ;
172
- }
173
-
174
- private string SerializeRequest ( object requestBody )
175
- {
176
- return requestBody == null
177
- ? null
178
- : requestBody is string stringRequestBody
179
- ? stringRequestBody
180
- : JsonConvert . SerializeObject ( requestBody ) ;
181
- }
182
-
183
- private TResponseDocument DeserializeResponse < TResponseDocument > ( string responseText )
184
- {
185
- if ( typeof ( TResponseDocument ) == typeof ( string ) )
186
- {
187
- return ( TResponseDocument ) ( object ) responseText ;
188
- }
189
-
190
- try
191
- {
192
- return JsonConvert . DeserializeObject < TResponseDocument > ( responseText ,
193
- IntegrationTestConfiguration . DeserializationSettings ) ;
194
- }
195
- catch ( JsonException exception )
196
- {
197
- throw new FormatException ( $ "Failed to deserialize response body to JSON:\n { responseText } ", exception ) ;
198
- }
199
- }
200
-
201
- private sealed class IntegrationTestWebApplicationFactory : WebApplicationFactory < EmptyStartup >
202
- {
203
- private Action < ILoggingBuilder > _loggingConfiguration ;
204
- private Action < IServiceCollection > _beforeServicesConfiguration ;
205
- private Action < IServiceCollection > _afterServicesConfiguration ;
206
-
207
- public void ConfigureLogging ( Action < ILoggingBuilder > loggingConfiguration )
208
- {
209
- _loggingConfiguration = loggingConfiguration ;
210
- }
211
-
212
- public void ConfigureServicesBeforeStartup ( Action < IServiceCollection > servicesConfiguration )
213
- {
214
- _beforeServicesConfiguration = servicesConfiguration ;
215
- }
216
-
217
- public void ConfigureServicesAfterStartup ( Action < IServiceCollection > servicesConfiguration )
218
- {
219
- _afterServicesConfiguration = servicesConfiguration ;
220
- }
221
-
222
- protected override IHostBuilder CreateHostBuilder ( )
223
- {
224
- return Host . CreateDefaultBuilder ( null )
225
- . ConfigureWebHostDefaults ( webBuilder =>
226
- {
227
- webBuilder . ConfigureLogging ( options =>
228
- {
229
- _loggingConfiguration ? . Invoke ( options ) ;
230
- } ) ;
231
-
232
- webBuilder . ConfigureServices ( services =>
233
- {
234
- _beforeServicesConfiguration ? . Invoke ( services ) ;
235
- } ) ;
236
-
237
- webBuilder . UseStartup < TStartup > ( ) ;
238
-
239
- webBuilder . ConfigureServices ( services =>
240
- {
241
- _afterServicesConfiguration ? . Invoke ( services ) ;
242
- } ) ;
243
- } ) ;
244
- }
245
- }
246
18
}
247
19
}
0 commit comments