Skip to content

Commit 05d69ff

Browse files
committed
test: mock NVD API calls, add nvd_integration marker
- conftest.py patches requests.get + time.sleep in cve_fetcher module - Skips mock for tests marked @pytest.mark.nvd_integration - Moves test_cve_fetcher.py module-level code into fixtures - pytest.ini excludes nvd_integration by default 66 tests now run in ~1s vs timing out at >120s
1 parent 4098f08 commit 05d69ff

3 files changed

Lines changed: 91 additions & 11 deletions

File tree

backend/analyzer/test/conftest.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from unittest.mock import patch
2+
3+
import pytest
4+
5+
MOCK_NVD_RESPONSE = {
6+
"vulnerabilities": [
7+
{
8+
"cve": {
9+
"id": "CVE-2021-44228",
10+
"published": "2025-01-01T00:00:00Z",
11+
"lastModified": "2025-01-01T00:00:00Z",
12+
"descriptions": [{"value": "A test vulnerability description."}],
13+
"metrics": {
14+
"cvssMetricV31": [
15+
{
16+
"cvssData": {
17+
"baseScore": 7.5,
18+
"baseSeverity": "HIGH",
19+
"attackVector": "NETWORK",
20+
"attackComplexity": "LOW",
21+
"privilegesRequired": "NONE",
22+
"userInteraction": "NONE",
23+
"confidentialityImpact": "HIGH",
24+
"integrityImpact": "NONE",
25+
"availabilityImpact": "NONE",
26+
"scope": "UNCHANGED",
27+
}
28+
}
29+
]
30+
},
31+
"weaknesses": [{"description": [{"value": "CWE-94"}]}],
32+
"references": [{"url": "https://example.com/advisory", "tags": ["Vendor Advisory"]}],
33+
}
34+
}
35+
]
36+
}
37+
38+
MOCK_EPSS_RESPONSE = {"data": [{"epss": 0.5}]}
39+
40+
41+
def _mock_requests_get(url, **kwargs):
42+
class MockResponse:
43+
def __init__(self, json_data, status_code):
44+
self.json_data = json_data
45+
self.status_code = status_code
46+
47+
def json(self):
48+
return self.json_data
49+
50+
url_str = str(url)
51+
if "nvd.nist.gov" in url_str:
52+
return MockResponse(MOCK_NVD_RESPONSE, 200)
53+
if "api.first.org" in url_str:
54+
return MockResponse(MOCK_EPSS_RESPONSE, 200)
55+
raise ConnectionError(f"Unexpected request: {url_str}")
56+
57+
58+
@pytest.fixture(autouse=True)
59+
def no_nvd_network(request):
60+
if request.node.get_closest_marker("nvd_integration"):
61+
yield
62+
return
63+
with patch("analyzer.services.cve_fetcher.requests.get", side_effect=_mock_requests_get), \
64+
patch("analyzer.services.cve_fetcher.time.sleep"):
65+
yield
Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,42 @@
11
from datetime import datetime
22

3+
import pytest
4+
35
from analyzer.services.cve_fetcher import CVEFetcher
46
from utilities.constants import BaseSeverity, AttackVector, AttackComplexity, UserInteraction, IntegrityImpact, \
57
AvailabilityImpact, ConfidentialityImpact, Scope, PrivilegesRequired
68

79
cve_id = "CVE-2021-44228"
8-
cve_fetcher = CVEFetcher(cve_id=cve_id)
9-
cve_data = cve_fetcher.generate()
1010

1111

12-
def test_description():
12+
@pytest.fixture
13+
def cve_data():
14+
fetcher = CVEFetcher(cve_id=cve_id)
15+
return fetcher.generate()
16+
17+
18+
@pytest.mark.nvd_integration
19+
def test_real_nvd_api_contract():
20+
fetcher = CVEFetcher(cve_id=cve_id)
21+
data = fetcher.generate()
22+
assert fetcher.successful
23+
assert len(data["description"]) > 0
24+
assert 0 < data["cve_attributes"]["baseScore"] <= 10
25+
26+
27+
def test_description(cve_data):
1328
assert len(cve_data["description"]) > 0
1429

1530

16-
def test_dates():
31+
def test_dates(cve_data):
1732
published = cve_data["published"]
1833
assert isinstance(published, datetime)
19-
2034
updated = cve_data["updated"]
2135
assert isinstance(updated, datetime)
2236

2337

24-
def test_cve_attributes_cvss_v3():
38+
def test_cve_attributes_cvss_v3(cve_data):
2539
attributes = cve_data["cve_attributes"]
26-
2740
assert 0 < attributes["baseScore"] <= 10
2841
assert attributes["baseSeverity"] in BaseSeverity.names
2942
assert attributes["attackVector"] in AttackVector.names
@@ -36,9 +49,9 @@ def test_cve_attributes_cvss_v3():
3649
assert attributes["scope"] in Scope.names
3750

3851

39-
def test_epss_score():
52+
def test_epss_score(cve_data):
4053
assert 0 <= float(cve_data["epss"]) <= 1.0
4154

4255

43-
def test_vendor_reference():
56+
def test_vendor_reference(cve_data):
4457
assert len(cve_data["vendor_reference"]) >= 0

backend/pytest.ini

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
[pytest]
2-
addopts = --nomigrations --reuse-db
3-
DJANGO_SETTINGS_MODULE = securecheckplus.settings
2+
addopts = --nomigrations --reuse-db -m "not nvd_integration"
3+
DJANGO_SETTINGS_MODULE = securecheckplus.settings
4+
markers =
5+
nvd_integration: tests that call the real NVD API (requires internet + API key)

0 commit comments

Comments
 (0)