Python Mockito库spy2作用于builtins.open时异常问题咨询
builtins.open vs os.path.exists? Great question! The discrepancy you're seeing comes down to how Mockito-python handles built-in functions versus regular module functions. Let's break this down step by step:
1. The Core Behavior Difference
When you use spy2 on a regular module function like os.path.exists:
- Mockito creates a proxy wrapper around the real function.
- For any call that doesn't match your stubbed arguments (e.g.,
folder_that_doesnt_exist), the proxy automatically forwards the call to the originalos.path.existsimplementation. - Only the explicitly stubbed argument (
.flake8) uses your custom return value.
But with builtins.open:
openis a built-in function implemented in C (not pure Python), and its function object has a different internal structure than regular module functions.- Mockito's
spy2can't properly create a proxy that falls back to the real implementation for unmatched calls. Instead, it defaults to strict stubbing mode—meaning every call toopenmust match an explicitly defined stub, otherwise it throws anInvocationError.
2. How to Fix It
To get the behavior you expect (stub only specific arguments, let others use the real open), you need to explicitly tell Mockito to fall back to the real method for unmatched calls. Add a catch-all stub that calls the real function before your specific stub:
import builtins import mockito mockito.spy2(builtins.open) # First, set a catch-all stub to call the real method for any unmatched arguments mockito.when(builtins).open(...).thenCallRealMethod() # Then add your specific stub mockito.when(builtins).open("not_existing_file.csv").thenReturn("test") print(builtins.open("not_existing_file.csv")) # Outputs "test" print(builtins.open("__init__.py")) # Opens the real file as expected mockito.unstub()
The ... (ellipsis) acts as a wildcard for any arguments, ensuring all calls that don't match your specific stub are forwarded to the real open function.
3. Why This Happens Under the Hood
Mockito-python relies on inspecting Python function objects to create its spy proxies. Built-in functions (from the builtins module) don't expose the same internal hooks as pure Python functions in regular modules. This makes it impossible for Mockito to automatically forward unmatched calls to the real implementation, so it switches to strict mode as a fallback.
Regular module functions like os.path.exists are pure Python (or at least expose a compatible function interface), so Mockito can wrap them properly to preserve the default real behavior.
内容的提问来源于stack exchange,提问作者Naindlac

