.NET Framework 4.8集成测试中如何覆盖配置切换测试数据库?
如何在.NET Framework 4.8集成测试中切换API的数据库连接字符串
我正在基于.NET Framework 4.8的应用上执行集成测试,使用Microsoft.VisualStudio.TestTools.UnitTesting框架。当前API默认指向生产数据库,我希望在集成测试时切换到测试数据库,需要找到修改API连接字符串的方法,让API在执行测试时使用集成测试的配置或连接字符串。
客户端代码
public static HttpResponseMessage WebApiGet(string path, string mediaType = "application/json") { var handler = new WebRequestHandler() { UseDefaultCredentials = true }; var virtualDirectory = ConfigurationManager.AppSettings["VirtualDirectory"]; using (var client = new HttpClient(handler)) { client.BaseAddress = new Uri(ConfigurationManager.AppSettings["InternalBaseAddress"]); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaType)); return client.GetAsync($"{virtualDirectory}{path}") .Result; } }
集成测试示例代码
[TestMethod] [TestCategory("IntegrationTest")] [TestCategory("House")] public async Task GetHOuseDetails_ShouldReturn200AndCorrectHOuseDetails() { var server = TestServer.Create<Startup>(); //Act var response = WebApiHelper.WebApiGet($"/api/house/details/{777777}"); //Assert Assert.IsTrue(response.IsSuccessStatusCode, "Get House Details fail"); var content = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject<HouseDetails>(content); Assert.AreEqual(777777, result.Id); }
集成测试项目app.config连接字符串说明
集成测试项目的app.config中配置了测试环境的数据库连接字符串,格式示例如下:
<connectionStrings> <add name="HouseDb" connectionString="Data Source=TEST_DB_SERVER;Initial Catalog=HouseTestDb;Integrated Security=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
API启动文件代码
using Castle.MicroKernel.Lifestyle; using Castle.Windsor; using Hangfire; using Hangfire.Dashboard; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Jet2.Memphis.Internal.Api.Startup))] namespace House.Api { public class Startup { public void Configuration(IAppBuilder app) { // Map Dashboard to the `http://<your-app>/hangfire` URL. app.UseHangfireDashboard("/hangfire", new DashboardOptions() { Authorization = new[] { new AllowAllDashboardAuthorizationFilter() } }); } } public class AllowAllDashboardAuthorizationFilter : IDashboardAuthorizationFilter { private IUserManager _userManager; private IWindsorContainer _container; public bool Authorize(DashboardContext context) { _container = ContainerManager.Container; using (_container.BeginScope()) { _userManager = _container.Resolve<IUserManager>(); return _userManager.HasPageAccess("hangfiredashboard"); } } } }
API端点代码
private readonly IMediator _mediator; [Route("api/house/details/{id}")] public async Task<IHttpActionResult> GetHouseDetails(int id) { var result = await _mediator.Send(new GetHouseDetailsQuery { HouseId = id }); if (result != null) return Ok(result); return NotFound(); }
解决方案
以下是几种实用的实现方式,可让API在集成测试时自动切换到测试数据库:
方法1:利用测试项目配置文件优先级
.NET Framework 中,使用TestServer启动API时,会优先加载测试项目的app.config,而非API项目的web.config。只需确保API通过ConfigurationManager.ConnectionStrings读取连接字符串,且测试项目app.config中配置了同名的测试环境连接字符串即可。
操作步骤:
- 确认API数据库访问代码使用
ConfigurationManager.ConnectionStrings["HouseDb"].ConnectionString获取连接字符串(若当前不是,需修改对应代码)。 - 在集成测试项目的app.config中添加与API项目同名的连接字符串,指向测试数据库(参考前文示例配置)。
- 确保测试项目已引用API项目,
TestServer.Create<Startup>()会自动加载测试项目的配置。
方法2:测试初始化阶段覆盖配置值
可在测试初始化时动态修改ConfigurationManager的配置项,强制API使用测试连接字符串:
修改后的集成测试代码:
[TestClass] public class HouseIntegrationTests { [TestInitialize] public void TestInitialize() { // 覆盖连接字符串 ConfigurationManager.ConnectionStrings["HouseDb"] = new ConnectionStringSettings( "HouseDb", "Data Source=TEST_DB_SERVER;Initial Catalog=HouseTestDb;Integrated Security=True;", "System.Data.SqlClient"); // 按需覆盖其他AppSettings项 ConfigurationManager.AppSettings["InternalBaseAddress"] = "http://localhost:port"; } [TestMethod] [TestCategory("IntegrationTest")] [TestCategory("House")] public async Task GetHOuseDetails_ShouldReturn200AndCorrectHOuseDetails() { var server = TestServer.Create<Startup>(); //Act var response = WebApiHelper.WebApiGet($"/api/house/details/{777777}"); //Assert Assert.IsTrue(response.IsSuccessStatusCode, "Get House Details fail"); var content = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject<HouseDetails>(content); Assert.AreEqual(777777, result.Id); } }
注意:需保证API启动时读取的是ConfigurationManager中的值,且测试初始化代码在TestServer启动前执行。
方法3:依赖注入替换数据库上下文
若API使用了Castle Windsor等依赖注入框架,可在测试中替换数据库上下文的注册逻辑,强制使用测试连接字符串:
操作示例:
var server = TestServer.Create(app => { // 自定义容器配置,替换测试用连接字符串 var container = new WindsorContainer(); container.Register(Component.For<IHouseDbContext>() .ImplementedBy<HouseDbContext>() .DependsOn(Dependency.OnValue("connectionString", "测试数据库连接字符串"))); // 保留原有Startup的其他配置 app.UseHangfireDashboard("/hangfire", new DashboardOptions() { Authorization = new[] { new AllowAllDashboardAuthorizationFilter() } }); });
这种方式更灵活,适合复杂依赖场景,避免直接修改ConfigurationManager。
内容的提问来源于stack exchange,提问作者DevSay
相关产品推荐
相关产品推荐

