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

如何让CSRF、DB连接、登录仅执行一次,重复运行待测试API?

一次性初始化+重复API测试实现方案

核心思路是把CSRF Token获取、数据库连接、登录这三个步骤放到测试套件的全局前置钩子中,让它们在整个测试流程启动时仅执行一次,后续所有测试用例直接复用初始化后的资源(比如认证Token、DB连接)来调用目标API。

以下是主流测试框架的具体实现示例:

1. Java JUnit 5

使用@BeforeAll注解标记初始化方法,该方法会在整个测试类的所有用例执行前仅运行一次:

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

public class APITestSuite {
    // 全局保存初始化后的资源
    private static DBConnection dbConnection;
    private static String authToken;
    private static String csrfToken;

    @BeforeAll
    public static void initGlobalResources() {
        // 1. 获取CSRF Token
        csrfToken = CsrfUtils.fetchToken();
        // 2. 建立数据库连接
        dbConnection = DBConnector.create();
        // 3. 执行登录获取认证Token
        authToken = AuthService.login(csrfToken, "testUser", "testPass");
    }

    @Test
    public void testTargetAPI_Get() {
        // 复用全局资源调用目标API
        APIResponse response = TargetAPI.callGet(authToken, csrfToken);
        assert response.getStatusCode() == 200;
    }

    @Test
    public void testTargetAPI_Post() {
        APIResponse response = TargetAPI.callPost(authToken, csrfToken, new TestPayload());
        assert response.getStatusCode() == 201;
    }

    // 省略工具类实现
    private static class CsrfUtils { public static String fetchToken() { /* ... */ } }
    private static class DBConnector { public static DBConnection create() { /* ... */ } }
    private static class AuthService { public static String login(String csrf, String u, String p) { /* ... */ } }
    private static class TargetAPI { 
        public static APIResponse callGet(String token, String csrf) { /* ... */ }
        public static APIResponse callPost(String token, String csrf, TestPayload payload) { /* ... */ }
    }
}

2. Python Pytest

使用scope="session"的fixture,该fixture会在整个测试会话(所有测试文件/用例)中仅执行一次:

import pytest
import requests

@pytest.fixture(scope="session")
def global_test_resources():
    # 1. 获取CSRF Token
    csrf_res = requests.get("http://your-domain/csrf-token")
    csrf_token = csrf_res.cookies.get("csrf_token")
    
    # 2. 建立数据库连接
    db_conn = get_db_connection()  # 自定义数据库连接方法
    
    # 3. 登录获取认证Token
    login_data = {"username": "test", "password": "test123", "csrf_token": csrf_token}
    login_res = requests.post("http://your-domain/login", data=login_data)
    auth_token = login_res.json()["auth_token"]
    
    # 返回复用资源
    yield {
        "db_conn": db_conn,
        "auth_token": auth_token,
        "csrf_token": csrf_token
    }
    
    # 测试会话结束后清理资源
    db_conn.close()

def test_api_scenario_1(global_test_resources):
    headers = {
        "Authorization": f"Bearer {global_test_resources['auth_token']}",
        "X-CSRF-Token": global_test_resources['csrf_token']
    }
    res = requests.get("http://your-domain/target-api", headers=headers)
    assert res.status_code == 200

def test_api_scenario_2(global_test_resources):
    headers = {
        "Authorization": f"Bearer {global_test_resources['auth_token']}",
        "X-CSRF-Token": global_test_resources['csrf_token']
    }
    payload = {"data": "test-content"}
    res = requests.post("http://your-domain/target-api", headers=headers, json=payload)
    assert res.status_code == 201

3. JavaScript Mocha

使用根级别的before钩子,该钩子会在整个测试套件所有用例执行前仅运行一次:

const request = require('superagent');
const db = require('./db-connector');

// 全局资源变量
let dbConnection;
let authToken;
let csrfToken;

// 全局初始化
before(async () => {
    // 1. 获取CSRF Token
    const csrfRes = await request.get('http://your-domain/api/csrf');
    csrfToken = csrfRes.headers['x-csrf-token'];

    // 2. 建立数据库连接
    dbConnection = await db.createConnection();

    // 3. 登录获取Token
    const loginRes = await request.post('http://your-domain/api/login')
        .set('X-CSRF-Token', csrfToken)
        .send({ username: 'test', password: 'test123' });
    authToken = loginRes.body.authToken;
});

// 测试用例组
describe('Target API Tests', () => {
    it('should handle GET request', async () => {
        const res = await request.get('http://your-domain/api/target')
            .set('Authorization', `Bearer ${authToken}`)
            .set('X-CSRF-Token', csrfToken);
        res.should.have.status(200);
    });

    it('should handle POST request', async () => {
        const res = await request.post('http://your-domain/api/target')
            .set('Authorization', `Bearer ${authToken}`)
            .set('X-CSRF-Token', csrfToken)
            .send({ content: 'test' });
        res.should.have.status(201);
    });
});

// 全局清理
after(async () => {
    await dbConnection.close();
});

关键注意事项

  • 资源清理:务必在测试会话结束后释放数据库连接等资源,避免内存泄漏。
  • 状态隔离:如果多次调用API会修改服务器或数据库状态,需在每个测试用例执行前通过@BeforeEach(JUnit)、scope="function"的fixture(Pytest)或beforeEach(Mocha)重置测试数据,确保用例之间互不干扰。
  • 并行测试:若启用并行测试,需确认框架对全局初始化的隔离策略,部分框架会为每个并行进程/线程单独执行一次初始化,需根据需求调整配置。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:11:02