|
3 | 3 | import time |
4 | 4 |
|
5 | 5 | import pytest |
| 6 | +from unittest.mock import Mock, MagicMock |
6 | 7 | from slack_sdk.signature import SignatureVerifier |
7 | 8 | from slack_sdk.web.async_client import AsyncWebClient |
8 | 9 |
|
|
17 | 18 | from tests.utils import remove_os_env_temporarily, restore_os_env |
18 | 19 |
|
19 | 20 |
|
| 21 | +async def fake_sleep(seconds): |
| 22 | + pass |
| 23 | + |
| 24 | + |
20 | 25 | class TestAsyncFunction: |
21 | 26 | signing_secret = "secret" |
22 | 27 | valid_token = "xoxb-valid" |
@@ -56,6 +61,10 @@ def build_request_from_body(self, message_body: dict) -> AsyncBoltRequest: |
56 | 61 | timestamp, body = str(int(time.time())), json.dumps(message_body) |
57 | 62 | return AsyncBoltRequest(body=body, headers=self.build_headers(timestamp, body)) |
58 | 63 |
|
| 64 | + def setup_time_mocks(self, *, monkeypatch: pytest.MonkeyPatch, time_mock: Mock, sleep_mock: MagicMock): |
| 65 | + monkeypatch.setattr(time, "time", time_mock) |
| 66 | + monkeypatch.setattr(asyncio, "sleep", sleep_mock) |
| 67 | + |
59 | 68 | @pytest.mark.asyncio |
60 | 69 | async def test_mock_server_is_running(self): |
61 | 70 | resp = await self.web_client.api_test() |
@@ -130,19 +139,49 @@ async def test_auto_acknowledge_false_with_acknowledging(self): |
130 | 139 | await assert_auth_test_count_async(self, 1) |
131 | 140 |
|
132 | 141 | @pytest.mark.asyncio |
133 | | - async def test_auto_acknowledge_false_without_acknowledging(self, caplog): |
| 142 | + async def test_auto_acknowledge_false_without_acknowledging(self, caplog, monkeypatch): |
134 | 143 | app = AsyncApp( |
135 | 144 | client=self.web_client, |
136 | 145 | signing_secret=self.signing_secret, |
137 | 146 | ) |
138 | 147 | app.function("reverse", auto_acknowledge=False)(just_no_ack) |
139 | | - |
140 | 148 | request = self.build_request_from_body(function_body) |
| 149 | + |
| 150 | + self.setup_time_mocks( |
| 151 | + monkeypatch=monkeypatch, |
| 152 | + time_mock=Mock(side_effect=[current_time for current_time in range(100)]), |
| 153 | + sleep_mock=MagicMock(side_effect=fake_sleep), |
| 154 | + ) |
| 155 | + |
141 | 156 | response = await app.async_dispatch(request) |
142 | 157 | assert response.status == 404 |
143 | 158 | await assert_auth_test_count_async(self, 1) |
144 | 159 | assert f"WARNING {just_no_ack.__name__} didn't call ack()" in caplog.text |
145 | 160 |
|
| 161 | + @pytest.mark.asyncio |
| 162 | + async def test_function_handler_timeout(self, monkeypatch): |
| 163 | + app = AsyncApp( |
| 164 | + client=self.web_client, |
| 165 | + signing_secret=self.signing_secret, |
| 166 | + ) |
| 167 | + app.function("reverse", auto_acknowledge=False)(just_no_ack) |
| 168 | + request = self.build_request_from_body(function_body) |
| 169 | + |
| 170 | + sleep_mock = MagicMock(side_effect=fake_sleep) |
| 171 | + self.setup_time_mocks( |
| 172 | + monkeypatch=monkeypatch, |
| 173 | + time_mock=Mock(side_effect=[current_time for current_time in range(100)]), |
| 174 | + sleep_mock=sleep_mock, |
| 175 | + ) |
| 176 | + |
| 177 | + response = await app.async_dispatch(request) |
| 178 | + |
| 179 | + assert response.status == 404 |
| 180 | + await assert_auth_test_count_async(self, 1) |
| 181 | + assert ( |
| 182 | + sleep_mock.call_count == 5 |
| 183 | + ), f"Expected handler to time out after calling time.sleep 5 times, but it was called {sleep_mock.call_count} times" |
| 184 | + |
146 | 185 |
|
147 | 186 | function_body = { |
148 | 187 | "token": "verification_token", |
|
0 commit comments