Skip to content

fix(test): Check method when comparing matchers #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions airbyte_cdk/test/mock_http/mocker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import contextlib
import functools
from collections import defaultdict
from enum import Enum
from types import TracebackType
from typing import Callable, List, Optional, Union
from typing import Callable, Dict, Iterable, List, Optional, Union

import requests_mock

Expand Down Expand Up @@ -40,7 +41,7 @@ class HttpMocker(contextlib.ContextDecorator):

def __init__(self) -> None:
self._mocker = requests_mock.Mocker()
self._matchers: List[HttpRequestMatcher] = []
self._matchers: Dict[SupportedHttpMethods, List[HttpRequestMatcher]] = defaultdict(list)

def __enter__(self) -> "HttpMocker":
self._mocker.__enter__()
Expand All @@ -55,7 +56,7 @@ def __exit__(
self._mocker.__exit__(exc_type, exc_val, exc_tb)

def _validate_all_matchers_called(self) -> None:
for matcher in self._matchers:
for matcher in self._get_matchers():
if not matcher.has_expected_match_count():
raise ValueError(f"Invalid number of matches for `{matcher}`")

Expand All @@ -69,9 +70,9 @@ def _mock_request_method(
responses = [responses]

matcher = HttpRequestMatcher(request, len(responses))
if matcher in self._matchers:
if matcher in self._matchers[method]:
raise ValueError(f"Request {matcher.request} already mocked")
self._matchers.append(matcher)
self._matchers[method].append(matcher)

getattr(self._mocker, method)(
requests_mock.ANY,
Expand Down Expand Up @@ -129,7 +130,7 @@ def matches(requests_mock_request: requests_mock.request._RequestObjectProxy) ->

def assert_number_of_calls(self, request: HttpRequest, number_of_calls: int) -> None:
corresponding_matchers = list(
filter(lambda matcher: matcher.request == request, self._matchers)
filter(lambda matcher: matcher.request is request, self._get_matchers())
)
if len(corresponding_matchers) != 1:
raise ValueError(
Expand All @@ -150,7 +151,7 @@ def wrapper(*args, **kwargs): # type: ignore # this is a very generic wrapper
result = f(*args, **kwargs)
except requests_mock.NoMockAddress as no_mock_exception:
matchers_as_string = "\n\t".join(
map(lambda matcher: str(matcher.request), self._matchers)
map(lambda matcher: str(matcher.request), self._get_matchers())
)
raise ValueError(
f"No matcher matches {no_mock_exception.args[0]} with headers `{no_mock_exception.request.headers}` "
Expand All @@ -175,6 +176,10 @@ def wrapper(*args, **kwargs): # type: ignore # this is a very generic wrapper

return wrapper

def _get_matchers(self) -> Iterable[HttpRequestMatcher]:
for matchers in self._matchers.values():
yield from matchers

def clear_all_matchers(self) -> None:
"""Clears all stored matchers by resetting the _matchers list to an empty state."""
self._matchers = []
self._matchers = defaultdict(list)
9 changes: 8 additions & 1 deletion unit_tests/test/mock_http/test_mocker.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,17 @@ def decorated_function(http_mocker):
with pytest.raises(ValueError):
decorated_function()

def test_given_request_already_mocked_when_decorate_then_raise(self):
def test_given_request_already_mocked_when_mock_then_raise(self):
with HttpMocker() as http_mocker:
a_request = HttpRequest(_A_URL, _SOME_QUERY_PARAMS, _SOME_HEADERS)
http_mocker.get(a_request, _A_RESPONSE)

with pytest.raises(ValueError):
http_mocker.get(a_request, _A_RESPONSE)

def test_given_same_request_with_different_method_when_mock_then_do_not_raise(self):
with HttpMocker() as http_mocker:
a_request = HttpRequest(_A_URL, _SOME_QUERY_PARAMS, _SOME_HEADERS)
http_mocker.get(a_request, _A_RESPONSE)

http_mocker.delete(a_request, _A_RESPONSE)
Loading