-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathWebApplicationFactory.cs
More file actions
107 lines (92 loc) · 4.08 KB
/
WebApplicationFactory.cs
File metadata and controls
107 lines (92 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using System.Data.Common;
using EssentialCSharp.Web.Data;
using EssentialCSharp.Web.Services;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Moq.AutoMock;
namespace EssentialCSharp.Web.Tests;
public sealed class WebApplicationFactory : WebApplicationFactory<Program>
{
private static string SqlConnectionString => $"DataSource=file:{Guid.NewGuid()}?mode=memory&cache=shared";
private SqliteConnection? _Connection;
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
ServiceDescriptor? dbContextDescriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(IDbContextOptionsConfiguration<EssentialCSharpWebContext>));
if (dbContextDescriptor != null)
{
services.Remove(dbContextDescriptor);
}
ServiceDescriptor? dbConnectionDescriptor =
services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbConnection));
if (dbConnectionDescriptor != null)
{
services.Remove(dbConnectionDescriptor);
}
_Connection = new SqliteConnection(SqlConnectionString);
_Connection.Open();
services.AddDbContext<EssentialCSharpWebContext>(options =>
{
options.UseSqlite(_Connection);
});
using ServiceProvider serviceProvider = services.BuildServiceProvider();
using IServiceScope scope = serviceProvider.CreateScope();
IServiceProvider scopedServices = scope.ServiceProvider;
EssentialCSharpWebContext db = scopedServices.GetRequiredService<EssentialCSharpWebContext>();
db.Database.EnsureCreated();
// Replace IListingSourceCodeService with one backed by TestData
services.RemoveAll<IListingSourceCodeService>();
string testDataPath = Path.Join(AppContext.BaseDirectory, "TestData");
var fileProvider = new PhysicalFileProvider(testDataPath);
services.AddSingleton<IListingSourceCodeService>(sp =>
{
var mocker = new AutoMocker();
mocker.Setup<IWebHostEnvironment, string>(m => m.ContentRootPath).Returns(testDataPath);
mocker.Setup<IWebHostEnvironment, IFileProvider>(m => m.ContentRootFileProvider).Returns(fileProvider);
return mocker.CreateInstance<ListingSourceCodeService>();
});
});
}
/// <summary>
/// Executes an action within a service scope, handling scope creation and cleanup automatically.
/// </summary>
/// <typeparam name="T">The return type of the action</typeparam>
/// <param name="action">The action to execute with the scoped service provider</param>
/// <returns>The result of the action</returns>
public T InServiceScope<T>(Func<IServiceProvider, T> action)
{
var factory = Services.GetRequiredService<IServiceScopeFactory>();
using var scope = factory.CreateScope();
return action(scope.ServiceProvider);
}
/// <summary>
/// Executes an action within a service scope, handling scope creation and cleanup automatically.
/// </summary>
/// <param name="action">The action to execute with the scoped service provider</param>
public void InServiceScope(Action<IServiceProvider> action)
{
var factory = Services.GetRequiredService<IServiceScopeFactory>();
using var scope = factory.CreateScope();
action(scope.ServiceProvider);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_Connection?.Dispose();
_Connection = null;
}
}
}