diff --git a/client/tests/sdk/utils.py b/client/tests/sdk/utils.py index 9659a668a6..8ac5b0a346 100644 --- a/client/tests/sdk/utils.py +++ b/client/tests/sdk/utils.py @@ -12,6 +12,24 @@ VCR = vcr.VCR(cassette_library_dir="tests/sdk/data/") +class Cassette(vcr.cassette.Cassette): + """Subclass `Cassette` to be able to handle two or more identical requests + with different responses at different positions in the cassette. Thanks to + @vickyliin for suggesting this workaround for kevin1024/vcrpy#753.""" + + def append_and_play(self, request, response) -> None: + prev_len_data = len(self.data) + super().append(request, response) + is_appended = len(self.data) == prev_len_data + 1 + if is_appended: + self.play_counts[prev_len_data] += 1 + + def _load(self) -> None: + super()._load() + self.append = self.append_and_play + self._load = None + + class VCRAPI(API): """Subclass `API` so that `_send_json_request()` is instrumented to record and replay VCR.py cassettes. @@ -53,7 +71,12 @@ def use_cassette(func): def wrapper(self, *args, **kwargs): # We have to specify an explicit path for each cassette because # we're not using vcr.use_cassette() directly as a decorator. - with VCR.use_cassette(f"{func.__name__}.yaml") as cassette: + context = VCR.use_cassette(f"{func.__name__}.yml") + + # Override `Cassette` to use our subclass before we enter the + # context manager. + context.cls = Cassette + with context as cassette: with patch.object(VCRAPI, "_cassette", cassette, create=True): return func(self, *args, **kwargs)