You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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中配置了同名的测试环境连接字符串即可。

操作步骤:

  1. 确认API数据库访问代码使用ConfigurationManager.ConnectionStrings["HouseDb"].ConnectionString获取连接字符串(若当前不是,需修改对应代码)。
  2. 在集成测试项目的app.config中添加与API项目同名的连接字符串,指向测试数据库(参考前文示例配置)。
  3. 确保测试项目已引用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:20:53