在测试期间模拟环境变量
mocking environment variables during testing
我有一个非常简单的 fastapi 应用程序,我想测试一下,dummy_api.py
的代码如下:
import os
from fastapi import FastAPI
app = FastAPI()
@app.get(os.getenv("ENDPOINT", "/get"))
def func():
return {
"message": "Endpoint working !!!"
}
当我想测试这个时,我正在使用以下文件:
from fastapi.testclient import TestClient
import dummy_api
def test_dummy_api():
client = TestClient(dummy_api.app)
response = client.get("/get")
assert response.status_code == 200
def test_dummy_api_with_envar(monkeypatch):
monkeypatch.setenv("ENDPOINT", "dummy")
client = TestClient(dummy_api.app)
response = client.get("/dummy")
assert response.status_code == 200
但是我无法模拟环境变量部分,因为其中一项测试失败并显示 404
。
pytest -s -v
================================================================= test session starts ==================================================================
platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1 -- /home/subhayan/anaconda3/envs/fastapi/bin/python
cachedir: .pytest_cache
rootdir: /home/subhayan/Codes/ai4bd/roughdir
collected 2 items
test_dummy_api.py::test_dummy_api PASSED
test_dummy_api.py::test_dummy_api_with_envar FAILED
======================================================================= FAILURES =======================================================================
______________________________________________________________ test_dummy_api_with_envar _______________________________________________________________
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7ff8c4cf1430>
def test_dummy_api_with_envar(monkeypatch):
monkeypatch.setenv("ENDPOINT", "dummy")
client = TestClient(dummy_api.app)
response = client.get("/dummy")
> assert response.status_code == 200
E assert 404 == 200
E +404
E -200
test_dummy_api.py:15: AssertionError
=============================================================== short test summary info ================================================================
FAILED test_dummy_api.py::test_dummy_api_with_envar - assert 404 == 200
============================================================= 1 failed, 1 passed in 0.19s ==============================================================
谁能指出我哪里错了!!
在我看来是这样的:
- 当测试文件被 pytest 加载时,所有可以在 dummy_api 中执行的东西都会被执行,因为它是导入的。
- 这意味着装饰函数(即@app.get(...))的装饰器将被执行。此时猴子修补还没有开始。
- 测试功能启动后,环境变量设置太晚了。
您可以使用 parametrized fixtures and the importlib.reload
function 来测试是否确实使用了环境变量。
我的测试目录如下所示:
.
└── tests
├── conftest.py
├── dummy_api.py
└── test_api.py
这是我的 conftest.py
:
import pytest
from fastapi.testclient import TestClient
from importlib import reload
import dummy_api
@pytest.fixture(params=["/get", "/dummy", "/other"])
def endpoint(request, monkeypatch):
monkeypatch.setenv("ENDPOINT", request.param)
return request.param
@pytest.fixture()
def client(endpoint):
app = reload(dummy_api).app
yield TestClient(app=app)
这里是 test_api.py
文件:
import os
def test_dummy_api(client):
endpoint = os.environ["ENDPOINT"]
response = client.get(endpoint)
assert response.status_code == 200
assert response.json() == {"message": f"Endpoint {endpoint} working !"}
运行pytest
后的测试输出:
collected 3 items
tests/test_api.py::test_dummy_api[/get] PASSED [ 33%]
tests/test_api.py::test_dummy_api[/dummy] PASSED [ 66%]
tests/test_api.py::test_dummy_api[/other] PASSED [100%]
我有一个非常简单的 fastapi 应用程序,我想测试一下,dummy_api.py
的代码如下:
import os
from fastapi import FastAPI
app = FastAPI()
@app.get(os.getenv("ENDPOINT", "/get"))
def func():
return {
"message": "Endpoint working !!!"
}
当我想测试这个时,我正在使用以下文件:
from fastapi.testclient import TestClient
import dummy_api
def test_dummy_api():
client = TestClient(dummy_api.app)
response = client.get("/get")
assert response.status_code == 200
def test_dummy_api_with_envar(monkeypatch):
monkeypatch.setenv("ENDPOINT", "dummy")
client = TestClient(dummy_api.app)
response = client.get("/dummy")
assert response.status_code == 200
但是我无法模拟环境变量部分,因为其中一项测试失败并显示 404
。
pytest -s -v
================================================================= test session starts ==================================================================
platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1 -- /home/subhayan/anaconda3/envs/fastapi/bin/python
cachedir: .pytest_cache
rootdir: /home/subhayan/Codes/ai4bd/roughdir
collected 2 items
test_dummy_api.py::test_dummy_api PASSED
test_dummy_api.py::test_dummy_api_with_envar FAILED
======================================================================= FAILURES =======================================================================
______________________________________________________________ test_dummy_api_with_envar _______________________________________________________________
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7ff8c4cf1430>
def test_dummy_api_with_envar(monkeypatch):
monkeypatch.setenv("ENDPOINT", "dummy")
client = TestClient(dummy_api.app)
response = client.get("/dummy")
> assert response.status_code == 200
E assert 404 == 200
E +404
E -200
test_dummy_api.py:15: AssertionError
=============================================================== short test summary info ================================================================
FAILED test_dummy_api.py::test_dummy_api_with_envar - assert 404 == 200
============================================================= 1 failed, 1 passed in 0.19s ==============================================================
谁能指出我哪里错了!!
在我看来是这样的:
- 当测试文件被 pytest 加载时,所有可以在 dummy_api 中执行的东西都会被执行,因为它是导入的。
- 这意味着装饰函数(即@app.get(...))的装饰器将被执行。此时猴子修补还没有开始。
- 测试功能启动后,环境变量设置太晚了。
您可以使用 parametrized fixtures and the importlib.reload
function 来测试是否确实使用了环境变量。
我的测试目录如下所示:
.
└── tests
├── conftest.py
├── dummy_api.py
└── test_api.py
这是我的 conftest.py
:
import pytest
from fastapi.testclient import TestClient
from importlib import reload
import dummy_api
@pytest.fixture(params=["/get", "/dummy", "/other"])
def endpoint(request, monkeypatch):
monkeypatch.setenv("ENDPOINT", request.param)
return request.param
@pytest.fixture()
def client(endpoint):
app = reload(dummy_api).app
yield TestClient(app=app)
这里是 test_api.py
文件:
import os
def test_dummy_api(client):
endpoint = os.environ["ENDPOINT"]
response = client.get(endpoint)
assert response.status_code == 200
assert response.json() == {"message": f"Endpoint {endpoint} working !"}
运行pytest
后的测试输出:
collected 3 items
tests/test_api.py::test_dummy_api[/get] PASSED [ 33%]
tests/test_api.py::test_dummy_api[/dummy] PASSED [ 66%]
tests/test_api.py::test_dummy_api[/other] PASSED [100%]