使用WebApplicationFactory内存运行API时,能否测试CORS策略?
测试基于WebApplicationFactory的内存API的CORS策略
你遇到的问题核心是:单纯发送不带特定头的OPTIONS请求,不会触发CORS中间件的完整校验逻辑。CORS中间件只会对符合跨域请求特征的请求执行校验——也就是必须同时携带Origin头(标识请求来源),以及针对预检请求的Access-Control-Request-Method头(声明要跨域调用的HTTP方法)。
要正确测试内存API的CORS策略,你需要构造符合浏览器跨域请求规范的请求,再校验响应的状态码和CORS头。以下是具体实现步骤:
关键测试要点
- 针对预检请求(OPTIONS方法):必须同时携带
Origin和Access-Control-Request-Method头 - 针对简单请求(如GET/POST):只需携带
Origin头,校验响应是否包含允许的CORS头
示例测试代码
public class CorsPolicyTests : IClassFixture<WebApplicationFactory<Program>> { private readonly WebApplicationFactory<Program> _webAppFactory; public CorsPolicyTests(WebApplicationFactory<Program> webAppFactory) { _webAppFactory = webAppFactory; } // 测试:不被允许的Origin发起预检请求,应返回403或无允许头 [Fact] public async Task Preflight_FromDisallowedOrigin_ReturnsForbidden() { // 构造请求 var client = _webAppFactory.CreateClient(); var request = new HttpRequestMessage(HttpMethod.Options, "/api/test-endpoint") { Headers = { { "Origin", "https://unauthorized-domain.com" }, { "Access-Control-Request-Method", "GET" } } }; // 发送请求 var response = await client.SendAsync(request); // 断言:返回403,且无允许跨域的头 Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); Assert.False(response.Headers.Contains("Access-Control-Allow-Origin")); } // 测试:被允许的Origin发起预检请求,应返回200并携带允许头 [Fact] public async Task Preflight_FromAllowedOrigin_ReturnsSuccessWithCorsHeaders() { var client = _webAppFactory.CreateClient(); var request = new HttpRequestMessage(HttpMethod.Options, "/api/test-endpoint") { Headers = { { "Origin", "https://authorized-domain.com" }, { "Access-Control-Request-Method", "POST" } } }; var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); Assert.True(response.Headers.Contains("Access-Control-Allow-Origin")); Assert.Equal("https://authorized-domain.com", response.Headers.GetValues("Access-Control-Allow-Origin").First()); } // 测试简单跨域请求的校验 [Fact] public async Task SimpleRequest_FromDisallowedOrigin_LacksCorsHeaders() { var client = _webAppFactory.CreateClient(); var request = new HttpRequestMessage(HttpMethod.Get, "/api/test-endpoint") { Headers = { { "Origin", "https://unauthorized-domain.com" } } }; var response = await client.SendAsync(request); // 简单请求不会返回403,但不会携带允许跨域的头 Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.False(response.Headers.Contains("Access-Control-Allow-Origin")); } }
额外注意事项
- 确保CORS中间件在Program.cs/Startup.cs中的位置正确:必须放在
UseRouting()之后,UseAuthorization()之前 - 如果你的CORS策略配置了
AllowAnyOrigin(),那么所有Origin都会被允许,测试逻辑需要对应调整 - 若测试中仍然无法触发校验,检查API端点是否正确关联了CORS策略(比如通过
[EnableCors]特性或全局配置)
内容的提问来源于stack exchange,提问作者Tom Troughton
相关产品推荐
相关产品推荐

