Skip to content

Commit b00b975

Browse files
committed
fix: correct test imports, patch targets, and async usage
- Add # noqa: E402 to document that env setup before import is required by the module's top-level code (same pattern as existing test_gitlab_webhook_port.py) - Fix mock.patch targets to use sys.modules injection instead of patching non-existent pr_agent.servers.gitlab_webhook.gitlab path - Use AsyncMock for _get_bot_user_id and asyncio.run() for calling now-async is_bot_assigned_as_reviewer and _get_bot_user_id Assisted-by: opencode:deepseek-v4-pro
1 parent ec9bf1e commit b00b975

1 file changed

Lines changed: 80 additions & 68 deletions

File tree

Lines changed: 80 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1+
import asyncio
12
import os
23
from unittest import mock
34

45
os.environ.setdefault("GITLAB__URL", "https://gitlab.example.com")
5-
import pr_agent.servers.gitlab_webhook as gitlab_webhook
6+
import pr_agent.servers.gitlab_webhook as gitlab_webhook # noqa: E402
67

78

89
class TestIsBotAssignedAsReviewer:
910
BOT_ID = 516
1011

11-
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", return_value=BOT_ID)
12-
def test_detects_new_assignment(self, _mock_bot_id):
12+
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", new_callable=mock.AsyncMock)
13+
def test_detects_new_assignment(self, mock_bot_id):
14+
mock_bot_id.return_value = self.BOT_ID
1315
data = {
1416
"changes": {
1517
"reviewers": {
@@ -18,10 +20,11 @@ def test_detects_new_assignment(self, _mock_bot_id):
1820
}
1921
}
2022
}
21-
assert gitlab_webhook.is_bot_assigned_as_reviewer(data) is True
23+
assert asyncio.run(gitlab_webhook.is_bot_assigned_as_reviewer(data)) is True
2224

23-
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", return_value=BOT_ID)
24-
def test_ignores_already_assigned(self, _mock_bot_id):
25+
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", new_callable=mock.AsyncMock)
26+
def test_ignores_already_assigned(self, mock_bot_id):
27+
mock_bot_id.return_value = self.BOT_ID
2528
data = {
2629
"changes": {
2730
"reviewers": {
@@ -30,28 +33,31 @@ def test_ignores_already_assigned(self, _mock_bot_id):
3033
}
3134
}
3235
}
33-
assert gitlab_webhook.is_bot_assigned_as_reviewer(data) is False
36+
assert asyncio.run(gitlab_webhook.is_bot_assigned_as_reviewer(data)) is False
3437

35-
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", return_value=BOT_ID)
36-
def test_no_reviewers_key(self, _mock_bot_id):
38+
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", new_callable=mock.AsyncMock)
39+
def test_no_reviewers_key(self, mock_bot_id):
40+
mock_bot_id.return_value = self.BOT_ID
3741
data = {"changes": {"updated_at": {"previous": "old", "current": "new"}}}
38-
assert gitlab_webhook.is_bot_assigned_as_reviewer(data) is False
42+
assert asyncio.run(gitlab_webhook.is_bot_assigned_as_reviewer(data)) is False
3943

4044
def test_changes_not_dict(self):
4145
data = {"changes": "not-a-dict"}
42-
assert gitlab_webhook.is_bot_assigned_as_reviewer(data) is False
46+
assert asyncio.run(gitlab_webhook.is_bot_assigned_as_reviewer(data)) is False
4347

44-
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", return_value=BOT_ID)
45-
def test_reviewers_not_dict(self, _mock_bot_id):
48+
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", new_callable=mock.AsyncMock)
49+
def test_reviewers_not_dict(self, mock_bot_id):
50+
mock_bot_id.return_value = self.BOT_ID
4651
data = {"changes": {"reviewers": "not-a-dict"}}
47-
assert gitlab_webhook.is_bot_assigned_as_reviewer(data) is False
52+
assert asyncio.run(gitlab_webhook.is_bot_assigned_as_reviewer(data)) is False
4853

4954
def test_no_changes_key(self):
5055
data = {"object_kind": "merge_request"}
51-
assert gitlab_webhook.is_bot_assigned_as_reviewer(data) is False
56+
assert asyncio.run(gitlab_webhook.is_bot_assigned_as_reviewer(data)) is False
5257

53-
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", return_value=None)
54-
def test_bot_id_unresolvable(self, _mock_bot_id):
58+
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", new_callable=mock.AsyncMock)
59+
def test_bot_id_unresolvable(self, mock_bot_id):
60+
mock_bot_id.return_value = None
5561
data = {
5662
"changes": {
5763
"reviewers": {
@@ -60,10 +66,11 @@ def test_bot_id_unresolvable(self, _mock_bot_id):
6066
}
6167
}
6268
}
63-
assert gitlab_webhook.is_bot_assigned_as_reviewer(data) is False
69+
assert asyncio.run(gitlab_webhook.is_bot_assigned_as_reviewer(data)) is False
6470

65-
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", return_value=BOT_ID)
66-
def test_previous_with_non_dict_entries(self, _mock_bot_id):
71+
@mock.patch.object(gitlab_webhook, "_get_bot_user_id", new_callable=mock.AsyncMock)
72+
def test_previous_with_non_dict_entries(self, mock_bot_id):
73+
mock_bot_id.return_value = self.BOT_ID
6774
data = {
6875
"changes": {
6976
"reviewers": {
@@ -72,50 +79,53 @@ def test_previous_with_non_dict_entries(self, _mock_bot_id):
7279
}
7380
}
7481
}
75-
assert gitlab_webhook.is_bot_assigned_as_reviewer(data) is True
82+
assert asyncio.run(gitlab_webhook.is_bot_assigned_as_reviewer(data)) is True
7683

7784

7885
class TestGetBotUserId:
86+
@staticmethod
87+
def _make_fake_gitlab(user_id):
88+
fake = mock.MagicMock()
89+
fake.Gitlab.return_value.auth.return_value = None
90+
fake.Gitlab.return_value.user.id = user_id
91+
return fake
92+
93+
@staticmethod
94+
def _make_settings(url, token):
95+
s = mock.MagicMock()
96+
s.get.side_effect = lambda k, d=None: {
97+
"GITLAB.URL": url,
98+
"GITLAB.PERSONAL_ACCESS_TOKEN": token,
99+
"GITLAB.SSL_VERIFY": True,
100+
"GITLAB.AUTH_TYPE": "oauth_token",
101+
}.get(k, d)
102+
return s
103+
79104
def test_caches_by_credential(self, monkeypatch):
80105
gitlab_webhook._bot_user_id_cache.clear()
81106

82-
from unittest.mock import MagicMock
83-
84-
def make_settings(url, token):
85-
s = MagicMock()
86-
s.get.side_effect = lambda k, d=None: {"GITLAB.URL": url, "GITLAB.PERSONAL_ACCESS_TOKEN": token, "GITLAB.SSL_VERIFY": True, "GITLAB.AUTH_TYPE": "oauth_token"}.get(k, d)
87-
return s
88-
89-
gl_mock = MagicMock()
90-
gl_mock.user.id = 111
91-
mock_gitlab_cls = MagicMock(return_value=gl_mock)
107+
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings",
108+
return_value=self._make_settings("https://a.example.com", "token-a")):
109+
with mock.patch.dict("sys.modules", {"gitlab": self._make_fake_gitlab(111)}):
110+
assert asyncio.run(gitlab_webhook._get_bot_user_id()) == 111
92111

93-
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings", return_value=make_settings("https://a.example.com", "token-a")):
94-
with mock.patch("pr_agent.servers.gitlab_webhook.gitlab.Gitlab", mock_gitlab_cls):
95-
assert gitlab_webhook._get_bot_user_id() == 111
96-
97-
gl_mock.user.id = 222
98-
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings", return_value=make_settings("https://a.example.com", "token-b")):
99-
with mock.patch("pr_agent.servers.gitlab_webhook.gitlab.Gitlab", mock_gitlab_cls):
100-
assert gitlab_webhook._get_bot_user_id() == 222
112+
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings",
113+
return_value=self._make_settings("https://a.example.com", "token-b")):
114+
with mock.patch.dict("sys.modules", {"gitlab": self._make_fake_gitlab(222)}):
115+
assert asyncio.run(gitlab_webhook._get_bot_user_id()) == 222
101116

102117
assert len(gitlab_webhook._bot_user_id_cache) >= 2
103118

104119
def test_negative_cache_on_failure(self, monkeypatch):
105120
gitlab_webhook._bot_user_id_cache.clear()
106121

107-
from unittest.mock import MagicMock
108-
109-
def make_settings():
110-
s = MagicMock()
111-
s.get.side_effect = lambda k, d=None: {"GITLAB.URL": "https://x.example.com", "GITLAB.PERSONAL_ACCESS_TOKEN": "fail-token", "GITLAB.SSL_VERIFY": True, "GITLAB.AUTH_TYPE": "oauth_token"}.get(k, d)
112-
return s
122+
fake = self._make_fake_gitlab(0)
123+
fake.Gitlab.side_effect = RuntimeError("auth failed")
113124

114-
mock_gitlab_cls = MagicMock(side_effect=RuntimeError("auth failed"))
115-
116-
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings", return_value=make_settings()):
117-
with mock.patch("pr_agent.servers.gitlab_webhook.gitlab.Gitlab", mock_gitlab_cls):
118-
assert gitlab_webhook._get_bot_user_id() is None
125+
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings",
126+
return_value=self._make_settings("https://x.example.com", "fail-token")):
127+
with mock.patch.dict("sys.modules", {"gitlab": fake}):
128+
assert asyncio.run(gitlab_webhook._get_bot_user_id()) is None
119129

120130
assert len(gitlab_webhook._bot_user_id_cache) == 1
121131
cached_val = next(iter(gitlab_webhook._bot_user_id_cache.values()))
@@ -124,32 +134,34 @@ def make_settings():
124134
def test_respects_auth_type_private_token(self):
125135
gitlab_webhook._bot_user_id_cache.clear()
126136

127-
from unittest.mock import MagicMock
128-
129-
def make_settings():
130-
s = MagicMock()
131-
s.get.side_effect = lambda k, d=None: {"GITLAB.URL": "https://x.example.com", "GITLAB.PERSONAL_ACCESS_TOKEN": "tok", "GITLAB.SSL_VERIFY": True, "GITLAB.AUTH_TYPE": "private_token"}.get(k, d)
132-
return s
137+
s = mock.MagicMock()
138+
s.get.side_effect = lambda k, d=None: {
139+
"GITLAB.URL": "https://x.example.com",
140+
"GITLAB.PERSONAL_ACCESS_TOKEN": "tok",
141+
"GITLAB.SSL_VERIFY": True,
142+
"GITLAB.AUTH_TYPE": "private_token",
143+
}.get(k, d)
133144

134-
gl_mock = MagicMock()
135-
gl_mock.user.id = 99
136-
mock_gitlab_cls = MagicMock(return_value=gl_mock)
145+
fake_gitlab = self._make_fake_gitlab(99)
137146

138-
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings", return_value=make_settings()):
139-
with mock.patch("pr_agent.servers.gitlab_webhook.gitlab.Gitlab", mock_gitlab_cls):
140-
assert gitlab_webhook._get_bot_user_id() == 99
147+
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings", return_value=s):
148+
with mock.patch.dict("sys.modules", {"gitlab": fake_gitlab}):
149+
assert asyncio.run(gitlab_webhook._get_bot_user_id()) == 99
141150

142-
call_kwargs = mock_gitlab_cls.call_args.kwargs
151+
call_kwargs = fake_gitlab.Gitlab.call_args.kwargs
143152
assert "private_token" in call_kwargs
144153
assert call_kwargs["private_token"] == "tok"
145154

146155
def test_no_token_returns_none(self, monkeypatch):
147156
gitlab_webhook._bot_user_id_cache.clear()
148157

149-
from unittest.mock import MagicMock
150-
151-
s = MagicMock()
152-
s.get.side_effect = lambda k, d=None: {"GITLAB.URL": "https://x.example.com", "GITLAB.PERSONAL_ACCESS_TOKEN": None, "GITLAB.SSL_VERIFY": True, "GITLAB.AUTH_TYPE": "oauth_token"}.get(k, d)
158+
s = mock.MagicMock()
159+
s.get.side_effect = lambda k, d=None: {
160+
"GITLAB.URL": "https://x.example.com",
161+
"GITLAB.PERSONAL_ACCESS_TOKEN": None,
162+
"GITLAB.SSL_VERIFY": True,
163+
"GITLAB.AUTH_TYPE": "oauth_token",
164+
}.get(k, d)
153165

154166
with mock.patch("pr_agent.servers.gitlab_webhook.get_settings", return_value=s):
155-
assert gitlab_webhook._get_bot_user_id() is None
167+
assert asyncio.run(gitlab_webhook._get_bot_user_id()) is None

0 commit comments

Comments
 (0)