统一测试辅助函数到 conftest.py,消除代码重复
This commit is contained in:
+44
-96
@@ -4,68 +4,14 @@ import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.routers import auth as auth_router
|
||||
from tests.conftest import bearer
|
||||
|
||||
ADMIN_EMAIL = "admin@example.com"
|
||||
ADMIN_PASSWORD = "admin-password-123"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _capture_email(monkeypatch) -> dict[str, str]:
|
||||
captured: dict[str, str] = {}
|
||||
|
||||
async def capture(recipient: str, token: str) -> None:
|
||||
captured["token"] = token
|
||||
|
||||
monkeypatch.setattr(auth_router, "send_confirmation_email", capture)
|
||||
return captured
|
||||
|
||||
|
||||
def _register(client: TestClient, email: str, password: str, username: str):
|
||||
return client.post(
|
||||
"/api/v1/auth/register",
|
||||
json={"email": email, "password": password, "username": username},
|
||||
)
|
||||
|
||||
|
||||
def _confirm(client: TestClient, token: str):
|
||||
return client.post("/api/v1/auth/confirm-email", json={"token": token})
|
||||
|
||||
|
||||
def _login(client: TestClient, email: str, password: str):
|
||||
return client.post(
|
||||
"/api/v1/auth/login",
|
||||
json={"email": email, "password": password},
|
||||
)
|
||||
|
||||
|
||||
def _register_and_confirm(
|
||||
client: TestClient,
|
||||
monkeypatch,
|
||||
email: str,
|
||||
password: str,
|
||||
username: str,
|
||||
) -> dict[str, str]:
|
||||
captured = _capture_email(monkeypatch)
|
||||
r = _register(client, email, password, username)
|
||||
assert r.status_code == 201
|
||||
token = captured.get("token")
|
||||
assert token
|
||||
cr = _confirm(client, token)
|
||||
assert cr.status_code == 200
|
||||
lr = _login(client, email, password)
|
||||
assert lr.status_code == 200
|
||||
body = lr.json()
|
||||
return {"token": body["access_token"], "user_id": body["user"]["id"]}
|
||||
|
||||
|
||||
def _login_as_user(client: TestClient, email: str, password: str) -> str:
|
||||
r = _login(client, email, password)
|
||||
return r.json()["access_token"]
|
||||
from tests.conftest import (
|
||||
bearer,
|
||||
capture_email,
|
||||
confirm_email,
|
||||
login_user,
|
||||
register_and_confirm,
|
||||
register_user,
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -75,8 +21,8 @@ def _login_as_user(client: TestClient, email: str, password: str) -> str:
|
||||
|
||||
def test_register_success(client: TestClient, monkeypatch) -> None:
|
||||
email = f"reg-{uuid.uuid4().hex[:8]}@example.com"
|
||||
captured = _capture_email(monkeypatch)
|
||||
r = _register(client, email, "regpassword", "注册测试")
|
||||
captured = capture_email(monkeypatch)
|
||||
r = register_user(client, email, "regpassword", "注册测试")
|
||||
assert r.status_code == 201
|
||||
assert r.json()["message"] == "注册成功,请查收确认邮件"
|
||||
assert "token" in captured
|
||||
@@ -84,8 +30,8 @@ def test_register_success(client: TestClient, monkeypatch) -> None:
|
||||
|
||||
def test_register_duplicate_email(client: TestClient, monkeypatch) -> None:
|
||||
email = f"dup-{uuid.uuid4().hex[:8]}@example.com"
|
||||
_register(client, email, "firstpass", "第一个用户")
|
||||
r = _register(client, email, "secondpass", "第二个用户")
|
||||
register_user(client, email, "firstpass", "第一个用户")
|
||||
r = register_user(client, email, "secondpass", "第二个用户")
|
||||
assert r.status_code == 409
|
||||
assert "该邮箱已被注册" == r.json()["detail"]
|
||||
|
||||
@@ -93,24 +39,24 @@ def test_register_duplicate_email(client: TestClient, monkeypatch) -> None:
|
||||
def test_register_duplicate_username(client: TestClient, monkeypatch) -> None:
|
||||
email_a = f"dupname-a-{uuid.uuid4().hex[:8]}@example.com"
|
||||
email_b = f"dupname-b-{uuid.uuid4().hex[:8]}@example.com"
|
||||
_register(client, email_a, "passA123", "同名用户")
|
||||
r = _register(client, email_b, "passB123", "同名用户")
|
||||
register_user(client, email_a, "passA123", "同名用户")
|
||||
r = register_user(client, email_b, "passB123", "同名用户")
|
||||
assert r.status_code == 409
|
||||
assert "这个昵称已经被使用" == r.json()["detail"]
|
||||
|
||||
|
||||
def test_register_short_password(client: TestClient) -> None:
|
||||
r = _register(client, f"s-{uuid.uuid4().hex[:8]}@e.com", "1234567", "短密码")
|
||||
r = register_user(client, f"s-{uuid.uuid4().hex[:8]}@e.com", "1234567", "短密码")
|
||||
assert r.status_code == 422
|
||||
|
||||
|
||||
def test_register_short_username(client: TestClient) -> None:
|
||||
r = _register(client, f"s-{uuid.uuid4().hex[:8]}@e.com", "pass12345", "A")
|
||||
r = register_user(client, f"s-{uuid.uuid4().hex[:8]}@e.com", "pass12345", "A")
|
||||
assert r.status_code == 422
|
||||
|
||||
|
||||
def test_register_invalid_email(client: TestClient) -> None:
|
||||
r = _register(client, "not-an-email", "pass12345", "坏邮箱")
|
||||
r = register_user(client, "not-an-email", "pass12345", "坏邮箱")
|
||||
assert r.status_code == 422
|
||||
|
||||
|
||||
@@ -121,18 +67,18 @@ def test_register_invalid_email(client: TestClient) -> None:
|
||||
|
||||
def test_confirm_email_valid(client: TestClient, monkeypatch) -> None:
|
||||
email = f"confirm-{uuid.uuid4().hex[:8]}@example.com"
|
||||
captured = _capture_email(monkeypatch)
|
||||
r = _register(client, email, "confirmpass", "确认测试")
|
||||
captured = capture_email(monkeypatch)
|
||||
r = register_user(client, email, "confirmpass", "确认测试")
|
||||
assert r.status_code == 201
|
||||
token = captured.get("token")
|
||||
assert token
|
||||
cr = _confirm(client, token)
|
||||
cr = confirm_email(client, token)
|
||||
assert cr.status_code == 200
|
||||
assert cr.json()["message"] == "邮箱确认成功"
|
||||
|
||||
|
||||
def test_confirm_email_invalid_token(client: TestClient) -> None:
|
||||
r = _confirm(client, "not-a-valid-token-at-all-never")
|
||||
r = confirm_email(client, "not-a-valid-token-at-all-never")
|
||||
assert r.status_code == 400
|
||||
assert "无效" in r.json()["detail"]
|
||||
|
||||
@@ -144,49 +90,51 @@ def test_confirm_email_invalid_token(client: TestClient) -> None:
|
||||
|
||||
def test_login_success(client: TestClient, monkeypatch) -> None:
|
||||
email = f"login-{uuid.uuid4().hex[:8]}@example.com"
|
||||
info = _register_and_confirm(client, monkeypatch, email, "loginpass", "登录测试")
|
||||
info = register_and_confirm(client, monkeypatch, email, "loginpass", "登录测试")
|
||||
assert info["token"]
|
||||
assert info["user_id"]
|
||||
|
||||
|
||||
def test_login_wrong_password(client: TestClient, monkeypatch) -> None:
|
||||
email = f"loginfail-{uuid.uuid4().hex[:8]}@example.com"
|
||||
_register_and_confirm(client, monkeypatch, email, "rightpass", "登录失败")
|
||||
r = _login(client, email, "wrongpass")
|
||||
register_and_confirm(client, monkeypatch, email, "rightpass", "登录失败")
|
||||
r = login_user(client, email, "wrongpass")
|
||||
assert r.status_code == 401
|
||||
assert "邮箱或密码错误" == r.json()["detail"]
|
||||
|
||||
|
||||
def test_login_nonexistent_email(client: TestClient) -> None:
|
||||
r = _login(client, "nobody@example.com", "whatever")
|
||||
r = login_user(client, "nobody@example.com", "whatever")
|
||||
assert r.status_code == 401
|
||||
|
||||
|
||||
def test_login_unverified_email(client: TestClient, monkeypatch) -> None:
|
||||
email = f"unverified-{uuid.uuid4().hex[:8]}@example.com"
|
||||
_capture_email(monkeypatch)
|
||||
_register(client, email, "unverified", "未确认")
|
||||
r = _login(client, email, "unverified")
|
||||
capture_email(monkeypatch)
|
||||
register_user(client, email, "unverified", "未确认")
|
||||
r = login_user(client, email, "unverified")
|
||||
assert r.status_code == 403
|
||||
assert "邮箱尚未确认" == r.json()["detail"]
|
||||
|
||||
|
||||
def test_login_disabled_user(client: TestClient, monkeypatch) -> None:
|
||||
from tests.conftest import ADMIN_EMAIL, ADMIN_PASSWORD
|
||||
|
||||
email = f"disabled-{uuid.uuid4().hex[:8]}@example.com"
|
||||
info = _register_and_confirm(client, monkeypatch, email, "disabled", "禁用测试")
|
||||
admin_token = _login_as_user(client, ADMIN_EMAIL, ADMIN_PASSWORD)
|
||||
info = register_and_confirm(client, monkeypatch, email, "disabled", "禁用测试")
|
||||
admin_tok = login_user(client, ADMIN_EMAIL, ADMIN_PASSWORD).json()["access_token"]
|
||||
client.patch(
|
||||
f"/api/v1/admin/users/{info['user_id']}",
|
||||
headers=bearer(admin_token),
|
||||
headers=bearer(admin_tok),
|
||||
json={"is_disabled": True},
|
||||
)
|
||||
r = _login(client, email, "disabled")
|
||||
r = login_user(client, email, "disabled")
|
||||
assert r.status_code == 403
|
||||
assert "账号已被禁用" == r.json()["detail"]
|
||||
|
||||
client.patch(
|
||||
f"/api/v1/admin/users/{info['user_id']}",
|
||||
headers=bearer(admin_token),
|
||||
headers=bearer(admin_tok),
|
||||
json={"is_disabled": False},
|
||||
)
|
||||
|
||||
@@ -198,7 +146,7 @@ def test_login_disabled_user(client: TestClient, monkeypatch) -> None:
|
||||
|
||||
def test_refresh_success(client: TestClient, monkeypatch) -> None:
|
||||
email = f"refresh-{uuid.uuid4().hex[:8]}@example.com"
|
||||
_register_and_confirm(client, monkeypatch, email, "refreshpass", "刷新测试")
|
||||
register_and_confirm(client, monkeypatch, email, "refreshpass", "刷新测试")
|
||||
r = client.post("/api/v1/auth/refresh")
|
||||
assert r.status_code == 200
|
||||
assert "access_token" in r.json()
|
||||
@@ -237,7 +185,7 @@ def test_logout(client: TestClient) -> None:
|
||||
|
||||
def test_forgot_password_existing_email(client: TestClient, monkeypatch) -> None:
|
||||
email = f"forgot-{uuid.uuid4().hex[:8]}@example.com"
|
||||
_register_and_confirm(client, monkeypatch, email, "forgotpass", "忘记密码")
|
||||
register_and_confirm(client, monkeypatch, email, "forgotpass", "忘记密码")
|
||||
captured = {}
|
||||
monkeypatch.setattr(auth_router, "send_password_reset_email", captured.__setitem__)
|
||||
r = client.post("/api/v1/auth/forgot-password", json={"email": email})
|
||||
@@ -252,7 +200,7 @@ def test_forgot_password_nonexistent_email(client: TestClient) -> None:
|
||||
|
||||
def test_reset_password_valid(client: TestClient, monkeypatch) -> None:
|
||||
email = f"reset-{uuid.uuid4().hex[:8]}@example.com"
|
||||
_register_and_confirm(client, monkeypatch, email, "oldpass12", "重置密码")
|
||||
register_and_confirm(client, monkeypatch, email, "oldpass12", "重置密码")
|
||||
captured = {}
|
||||
monkeypatch.setattr(auth_router, "send_password_reset_email", lambda r, t: captured.update(token=t))
|
||||
|
||||
@@ -267,9 +215,9 @@ def test_reset_password_valid(client: TestClient, monkeypatch) -> None:
|
||||
assert r.status_code == 200
|
||||
assert r.json()["message"] == "密码已重置,请重新登录"
|
||||
|
||||
r = _login(client, email, "oldpass12")
|
||||
r = login_user(client, email, "oldpass12")
|
||||
assert r.status_code == 401
|
||||
r = _login(client, email, "newpass12")
|
||||
r = login_user(client, email, "newpass12")
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
@@ -289,7 +237,7 @@ def test_reset_password_invalid_token(client: TestClient) -> None:
|
||||
|
||||
def test_change_password(client: TestClient, monkeypatch) -> None:
|
||||
email = f"chpw-{uuid.uuid4().hex[:8]}@example.com"
|
||||
info = _register_and_confirm(client, monkeypatch, email, "oldpass12", "改密")
|
||||
info = register_and_confirm(client, monkeypatch, email, "oldpass12", "改密")
|
||||
r = client.patch(
|
||||
"/api/v1/auth/password",
|
||||
headers=bearer(info["token"]),
|
||||
@@ -298,9 +246,9 @@ def test_change_password(client: TestClient, monkeypatch) -> None:
|
||||
assert r.status_code == 200
|
||||
assert "access_token" in r.json()
|
||||
|
||||
r = _login(client, email, "oldpass12")
|
||||
r = login_user(client, email, "oldpass12")
|
||||
assert r.status_code == 401
|
||||
r = _login(client, email, "updatedpass12")
|
||||
r = login_user(client, email, "updatedpass12")
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
@@ -311,7 +259,7 @@ def test_change_password(client: TestClient, monkeypatch) -> None:
|
||||
|
||||
def test_me(client: TestClient, monkeypatch) -> None:
|
||||
email = f"me-{uuid.uuid4().hex[:8]}@example.com"
|
||||
info = _register_and_confirm(client, monkeypatch, email, "mepass12!", "我的信息")
|
||||
info = register_and_confirm(client, monkeypatch, email, "mepass12!", "我的信息")
|
||||
r = client.get("/api/v1/auth/me", headers=bearer(info["token"]))
|
||||
assert r.status_code == 200
|
||||
body = r.json()
|
||||
|
||||
Reference in New Issue
Block a user