public TestFunctionHost(string scriptPath, string logPath, Action <IServiceCollection> configureWebHostServices = null, Action <IWebJobsBuilder> configureScriptHostWebJobsBuilder = null, Action <IConfigurationBuilder> configureScriptHostAppConfiguration = null, Action <ILoggingBuilder> configureScriptHostLogging = null, Action <IServiceCollection> configureScriptHostServices = null) { _appRoot = scriptPath; _hostOptions = new ScriptApplicationHostOptions { IsSelfHost = true, ScriptPath = _appRoot, LogPath = logPath, SecretsPath = Environment.CurrentDirectory, // not used HasParentScope = true }; var builder = new WebHostBuilder() .ConfigureLogging(b => { b.AddProvider(_webHostLoggerProvider); }) .ConfigureServices(services => { services.Replace(new ServiceDescriptor(typeof(ISecretManagerProvider), new TestSecretManagerProvider(new TestSecretManager()))); services.Replace(ServiceDescriptor.Singleton <IServiceProviderFactory <IServiceCollection> >(new WebHostServiceProviderFactory())); services.Replace(new ServiceDescriptor(typeof(IOptions <ScriptApplicationHostOptions>), sp => { _hostOptions.RootServiceProvider = sp; return(new OptionsWrapper <ScriptApplicationHostOptions>(_hostOptions)); }, ServiceLifetime.Singleton)); services.Replace(new ServiceDescriptor(typeof(IOptionsMonitor <ScriptApplicationHostOptions>), sp => { _hostOptions.RootServiceProvider = sp; return(TestHelpers.CreateOptionsMonitor(_hostOptions)); }, ServiceLifetime.Singleton)); services.Replace(new ServiceDescriptor(typeof(IExtensionBundleManager), new TestExtensionBundleManager())); services.Replace(new ServiceDescriptor(typeof(IFunctionMetadataManager), sp => { var montior = sp.GetService <IOptionsMonitor <ScriptApplicationHostOptions> >(); var scriptManager = sp.GetService <IScriptHostManager>(); var loggerFactory = sp.GetService <ILoggerFactory>(); return(GetMetadataManager(montior, scriptManager, loggerFactory)); }, ServiceLifetime.Singleton)); // Allows us to configure services as the last step, thereby overriding anything services.AddSingleton(new PostConfigureServices(configureWebHostServices)); }) .ConfigureScriptHostWebJobsBuilder(scriptHostWebJobsBuilder => { scriptHostWebJobsBuilder.AddAzureStorage(); configureScriptHostWebJobsBuilder?.Invoke(scriptHostWebJobsBuilder); }) .ConfigureScriptHostAppConfiguration(scriptHostConfigurationBuilder => { scriptHostConfigurationBuilder.AddTestSettings(); configureScriptHostAppConfiguration?.Invoke(scriptHostConfigurationBuilder); }) .ConfigureScriptHostLogging(scriptHostLoggingBuilder => { scriptHostLoggingBuilder.AddProvider(_scriptHostLoggerProvider); scriptHostLoggingBuilder.AddFilter <TestLoggerProvider>(_ => true); configureScriptHostLogging?.Invoke(scriptHostLoggingBuilder); }) .ConfigureScriptHostServices(scriptHostServices => { configureScriptHostServices?.Invoke(scriptHostServices); }) .UseStartup <TestStartup>(); _testServer = new TestServer(builder) { BaseAddress = new Uri("https://localhost/") }; HttpClient = _testServer.CreateClient(); var manager = _testServer.Host.Services.GetService <IScriptHostManager>(); _hostService = manager as WebJobsScriptHostService; // Wire up StopApplication calls as they behave in hosted scenarios var lifetime = WebHostServices.GetService <IApplicationLifetime>(); lifetime.ApplicationStopping.Register(async() => await _testServer.Host.StopAsync()); StartAsync().GetAwaiter().GetResult(); }
public TestFunctionHost(string scriptPath, string logPath, Action <IServiceCollection> configureWebHostServices = null, Action <IWebJobsBuilder> configureScriptHostWebJobsBuilder = null, Action <IConfigurationBuilder> configureScriptHostAppConfiguration = null, Action <ILoggingBuilder> configureScriptHostLogging = null, Action <IServiceCollection> configureScriptHostServices = null) { _appRoot = scriptPath; _hostOptions = new ScriptApplicationHostOptions { IsSelfHost = true, ScriptPath = _appRoot, LogPath = logPath, SecretsPath = Environment.CurrentDirectory, // not used HasParentScope = true }; var builder = new WebHostBuilder() .ConfigureLogging(b => { b.AddProvider(_webHostLoggerProvider); }) .ConfigureServices(services => { services.Replace(new ServiceDescriptor(typeof(ISecretManagerProvider), new TestSecretManagerProvider(new TestSecretManager()))); services.Replace(ServiceDescriptor.Singleton <IServiceProviderFactory <IServiceCollection> >(new WebHostServiceProviderFactory())); services.Replace(new ServiceDescriptor(typeof(IOptions <ScriptApplicationHostOptions>), sp => { _hostOptions.RootServiceProvider = sp; return(new OptionsWrapper <ScriptApplicationHostOptions>(_hostOptions)); }, ServiceLifetime.Singleton)); services.Replace(new ServiceDescriptor(typeof(IOptionsMonitor <ScriptApplicationHostOptions>), sp => { _hostOptions.RootServiceProvider = sp; return(TestHelpers.CreateOptionsMonitor(_hostOptions)); }, ServiceLifetime.Singleton)); services.Replace(new ServiceDescriptor(typeof(IExtensionBundleManager), new TestExtensionBundleManager())); services.Replace(new ServiceDescriptor(typeof(IFunctionMetadataManager), sp => { var montior = sp.GetService <IOptionsMonitor <ScriptApplicationHostOptions> >(); var scriptManager = sp.GetService <IScriptHostManager>(); var loggerFactory = sp.GetService <ILoggerFactory>(); var environment = sp.GetService <IEnvironment>(); return(GetMetadataManager(montior, scriptManager, loggerFactory, environment)); }, ServiceLifetime.Singleton)); services.SkipDependencyValidation(); // Allows us to configure services as the last step, thereby overriding anything services.AddSingleton(new PostConfigureServices(configureWebHostServices)); }) .ConfigureScriptHostWebJobsBuilder(scriptHostWebJobsBuilder => { /// REVIEW THIS scriptHostWebJobsBuilder.AddAzureStorage(); configureScriptHostWebJobsBuilder?.Invoke(scriptHostWebJobsBuilder); }) .ConfigureScriptHostAppConfiguration(scriptHostConfigurationBuilder => { scriptHostConfigurationBuilder.AddTestSettings(); configureScriptHostAppConfiguration?.Invoke(scriptHostConfigurationBuilder); }) .ConfigureScriptHostLogging(scriptHostLoggingBuilder => { scriptHostLoggingBuilder.AddProvider(_scriptHostLoggerProvider); scriptHostLoggingBuilder.AddFilter <TestLoggerProvider>(_ => true); configureScriptHostLogging?.Invoke(scriptHostLoggingBuilder); }) .ConfigureScriptHostServices(scriptHostServices => { configureScriptHostServices?.Invoke(scriptHostServices); }) .ConfigureAppConfiguration((builderContext, config) => { // replace the default environment source with our own IConfigurationSource envVarsSource = config.Sources.OfType <EnvironmentVariablesConfigurationSource>().FirstOrDefault(); if (envVarsSource != null) { config.Sources.Remove(envVarsSource); } config.Add(new ScriptEnvironmentVariablesConfigurationSource()); config.AddTestSettings(); }) .UseStartup <TestStartup>(); _testServer = new TestServer(builder) { BaseAddress = new Uri("https://localhost/") }; HttpClient = _testServer.CreateClient(); HttpClient.Timeout = TimeSpan.FromMinutes(5); var manager = _testServer.Host.Services.GetService <IScriptHostManager>(); _hostService = manager as WebJobsScriptHostService; // Wire up StopApplication calls as they behave in hosted scenarios var lifetime = WebHostServices.GetService <IApplicationLifetime>(); lifetime.ApplicationStopping.Register(async() => await _testServer.Host.StopAsync()); StartAsync().GetAwaiter().GetResult(); _stillRunningTimer = new Timer(StillRunningCallback, _testServer, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)); // store off a bit of the creation stack for easier debugging if this host doesn't shut down. var stack = new StackTrace(true).ToString().Split(Environment.NewLine).Take(5); _createdStack = string.Join($"{Environment.NewLine} ", stack); // cache startup logs since tests clear logs from time to time StartupLogs = GetScriptHostLogMessages(); }