簡體   English   中英

如何使用 Fast API 中的夾具和 pytest 在單個測試中跳過身份驗證?

[英]How can I skip authentication in a single test with a fixture in Fast API together with pytest?

我已經建立了類似於文檔中描述的身份驗證。 所以我從那里復制了這個依賴項:

async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user

我在一組端點中使用它,例如,在文檔的另一個示例中,對於User我有GETPOSTPUTDELETEGET ALL

唯一不需要身份驗證的方法是創建新用戶的 POST 方法。

我希望能夠定義單元測試來驗證沒有身份驗證就無法訪問該方法,並且當我專注於方法的內容時,我想完全跳過身份驗證。

因此,我在夾具中使用了覆蓋功能。 例如對於這個測試:

test_user.py

def test_create_user(test_db, create_user, user, skip_authentication):
    """
    Verify a user can be created and retrieved
    """
    response = client.post(
        "/api/v1/users/",
        json=create_user,
    )

    # Assert creation
    assert response.status_code == 200, response.text
    data = response.json()
    assert "id" in data
    user_id = data["id"]
    del data["id"]
    assert data == user

    # Assert get user
    response = client.get(f"/api/v1/users/{user_id}")
    assert response.status_code == 200, response.text
    data = response.json()
    assert user_id == data["id"]
    del data["id"]
    assert data == user

conftest.py

@pytest.fixture
def skip_authentication() -> None:

    def get_current_user():
        pass
    app.dependency_overrides[get_current_active_user] = get_current_user

這似乎可以刪除身份驗證,但它會在所有測試中刪除它,而不僅僅是在帶有夾具skip_authentication的測試中。

我怎樣才能將它限制在我想要的測試中?

我創建了pytest-fastapi-deps庫,它允許輕松定義和清理 FastAPI 依賴項。

像這樣使用它,它只會影響一個測試:

def test_create_user(test_db, create_user, user, fastapi_dep):
    """
    Verify a user can be created and retrieved
    """
    def skip_auth():
        pass
    with fastapi_dep(app).override({get_current_active_user: skip_auth}):
        response = client.post(
            "/api/v1/users/",
            json=create_user,
        )

        # Assert creation
        assert response.status_code == 200, response.text
        data = response.json()
        assert "id" in data
        user_id = data["id"]
        del data["id"]
        assert data == user

        # Assert get user
        response = client.get(f"/api/v1/users/{user_id}")
        assert response.status_code == 200, response.text
        data = response.json()
        assert user_id == data["id"]
        del data["id"]
        assert data == user

在@MatsLindh 的評論之后,我能夠讓它發揮作用。 我不確定是否是理想的解決方案,但對我有用。

我創建了兩個固定裝置,一個用於經過身份驗證的用戶,另一個用於其他測試:

conftest.py

@pytest.fixture
def client():
    """
    Return an API Client
    """
    app.dependency_overrides = {}
    return TestClient(app)

@pytest.fixture
def client_authenticated():
    """
    Returns an API client which skips the authentication
    """
    def skip_auth():
        pass
    app.dependency_overrides[get_current_active_user] = skip_auth
    return TestClient(app)

然后我能夠測試我的正常測試並驗證身份驗證:

def test_premissions_user(client, test_db, create_user):
    """
    Verify that not logged in users can not access the user functions excluding create
    """
    # Create user
    response = client.post(
        "/api/v1/users/",
        json=create_user
    )
    assert response.status_code == 200, response.text

    # Get all users
    response = client.get(
        "/api/v1/users/",
    )
    assert response.status_code == 401, response.text
    
    # Get user 1
    response = client.get(
        "/api/v1/users/1",
    )
    assert response.status_code == 401, response.text        
    
    # Delete user 1
    response = client.get(
        "/api/v1/users/1",
    )
    assert response.status_code == 401, response.text    
    
    # Modify user 1
    response = client.delete(
        "/api/v1/users/1",
    )
    assert response.status_code == 401, response.text

def test_premissions_user_authenticated(client_authenticated, test_db, create_user):
    """
    Verify that not logged in users can not access the user functions excluding create
    """
    # Create user
    response = client_authenticated.post(
        "/api/v1/users/",
        json=create_user
    )
    assert response.status_code == 200, response.text

    # Get all users
    response = client_authenticated.get(
        "/api/v1/users/",
    )
    assert response.status_code == 200, response.text
    
    # Get user 1
    response = client_authenticated.get(
        "/api/v1/users/1",
    )
    assert response.status_code == 200, response.text        
    
    # Delete user 1
    response = client_authenticated.get(
        "/api/v1/users/1",
    )
    assert response.status_code == 200, response.text    
    
    # Modify user 1
    response = client_authenticated.delete(
        "/api/v1/users/1",
    )
    assert response.status_code == 204, response.text

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM