/// <summary> /// Runs this fixture. /// </summary> /// <param name="output">The test output helper.</param> /// <returns></returns> public async Task RunAsync(ITestOutputHelper output = null) { _run = true; try { if (RequestMessage == null) { throw new InvalidOperationException($"Must call {nameof(When)} to configure an HTTP request"); } if (!_assertions.Any()) { throw new InvalidOperationException("No assertions to run"); } if (output != null) { _loggerProvider.SetTestOutputHelper(output); } using var client = Factory.CreateClient(); var provider = Factory.Server.Services; // Bootstrap. if (_bootstrapFunctions.Any()) { using var scope = provider.CreateScope(); foreach (var bootstrap in _bootstrapFunctions) { await bootstrap(scope.ServiceProvider); } } var logger = provider.GetRequiredService <ILogger <MvcFunctionalTestFixture <TStartup> > >(); var requestBody = await(RequestMessage.Content?.ReadAsStringAsync() ?? Task.FromResult <string>(null)); logger.LogInformation($"Sending request {RequestMessage}\n{requestBody ?? "<no body>"}"); var response = await client.SendAsync(RequestMessage); var responseBody = await(response.Content?.ReadAsStringAsync() ?? Task.FromResult <string>(null)); logger.LogInformation($"Received {response}\n{responseBody ?? "<no body>"}"); var aggregator = new ExceptionAggregator(); foreach (var assertion in _assertions) { switch (assertion) { case ResponseAssertion ra: aggregator.Run(() => ra.Assertion(response)); break; case ResponseBodyAssertion ra: if (aggregator.TryRun(() => ra.Deserializer(responseBody), out var result)) { foreach (var a in ra.Assertions) { await aggregator.RunAsync(() => a(provider, result)); } } break; case ServiceAssertion sa: using (var scope = provider.CreateScope()) { await aggregator.RunAsync(() => sa.Assertion(scope.ServiceProvider)); } break; case RequestAssertion ra: var context = await ra.ContextFactory(response); var fixture = new MvcFunctionalTestFixture <TStartup>(_loggerProvider, this); ra.Configurator(context, fixture); await aggregator.RunAsync(() => fixture.RunAsync()); break; } } aggregator.ThrowIfHasExceptions(); } finally { Reset(); } }