{"id":8325,"library":"mock-open","title":"Mock Open","description":"The `mock-open` library (current version 1.4.0) provides an enhanced mock object for testing file I/O operations in Python. It extends `unittest.mock.mock_open` to offer more realistic behavior for file-like objects, including robust handling of `with` statements, `read`, `write`, `seek`, and binary modes. It is actively maintained with releases addressing compatibility and feature enhancements.","status":"active","version":"1.4.0","language":"en","source_language":"en","source_url":"https://github.com/nivbend/mock-open","tags":["mocking","testing","file_io","unittest.mock"],"install":[{"cmd":"pip install mock-open","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"symbol":"MockOpen","correct":"from mock_open import MockOpen"},{"note":"Commonly used with MockOpen for patching 'builtins.open'.","symbol":"patch","correct":"from unittest.mock import patch"}],"quickstart":{"code":"from unittest.mock import patch\nfrom mock_open import MockOpen\n\n# Scenario 1: Mocking file reading\nmock_data_to_read = \"Line 1\\nLine 2\\nLine 3\"\nmo_read = MockOpen(read_data=mock_data_to_read)\n\nwith patch(\"builtins.open\", mo_read):\n    with open(\"my_input.txt\", \"r\") as f:\n        content = f.read()\n        lines = f.readlines()\n\n    assert content == mock_data_to_read\n    assert lines == [\"Line 1\\n\", \"Line 2\\n\", \"Line 3\"]\n    mo_read.assert_called_with(\"my_input.txt\", \"r\")\n\n# Scenario 2: Mocking file writing\nmo_write = MockOpen()\n\nwith patch(\"builtins.open\", mo_write):\n    with open(\"my_output.txt\", \"w\") as f:\n        f.write(\"Hello, world!\")\n        f.write(\"Python is great.\")\n\n    # Access the mock handle to verify writes\n    mo_write.mock_handle.write.assert_any_call(\"Hello, world!\")\n    mo_write.mock_handle.write.assert_any_call(\"Python is great.\")\n    mo_write.assert_called_with(\"my_output.txt\", \"w\")\n\n    # You can get the content written to the mock\n    written_content = \"\".join(call.args[0] for call in mo_write.mock_handle.write.call_args_list)\n    assert written_content == \"Hello, world!Python is great.\"\n\nprint(\"Mocking successful!\")","lang":"python","description":"This quickstart demonstrates how to use `mock-open` to patch `builtins.open` for both reading and writing operations. It shows how to initialize `MockOpen` with `read_data` and how to inspect written content via `mock_handle.write` calls."},"warnings":[{"fix":"Update tests to use `MockOpen(read_data='...')` for reading, or access `mo.mock_handle.write.assert_called_with(...)` for writing, rather than setting `side_effect` on the `MockOpen` instance itself for content.","message":"Prior to v1.3.0, `mock-open` often required contrived `side_effect` workarounds for file operations (`read`, `write`, `seek`). V1.3.0 changed this to use direct mock wrapping, making `return_value` and direct attribute access (`.mock_handle.read`) the correct way to interact. Code relying on `side_effect` for content might break.","severity":"breaking","affected_versions":"<1.3.0"},{"fix":"Ensure tests account for the file pointer being reset for each new `open` call when patching. If sequential reads from the *same* `open` call are needed, configure `read_data` or `side_effect` appropriately. If you relied on position persistence across *multiple* `open` calls, re-evaluate your test logic.","message":"In `mock-open` v1.4.0+, consecutive calls to a patched `open` function will reset the file-like mock's internal position (like `seek(0)`). In previous versions, the position might have persisted across different `with open(...)` blocks using the same mock, leading to unexpected behavior in subsequent reads.","severity":"gotcha","affected_versions":"<1.4.0"},{"fix":"Use `b'your binary data'` for `read_data` and assert against `bytes` objects when testing binary file modes. For text modes, use `str`.","message":"When mocking binary file operations (`'rb'`, `'wb'`, etc.) with `mock-open` (v1.3.0+), the underlying content storage uses `io.BytesIO`. Ensure that `read_data` provided for binary modes is a `bytes` object, not a `str`, and that assertions check for `bytes` content.","severity":"gotcha","affected_versions":">=1.3.0"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"After patching `builtins.open` with a `MockOpen` instance (`mo`), you must interact with the file object returned by `open` (e.g., `with open(...) as f: f.read()`) or directly access `mo.mock_handle` for assertions (e.g., `mo.mock_handle.read.assert_called_once()`).","cause":"Attempting to call file-like methods (like `read()`, `write()`, `seek()`) directly on the `MockOpen` instance instead of on the mock file handle returned by `open()` or accessed via `mo.mock_handle`.","error":"AttributeError: 'MockOpen' object has no attribute 'read'"},{"fix":"When initializing `MockOpen`, pass the expected content as a string (or bytes for binary mode) to the `read_data` parameter: `mo = MockOpen(read_data='Expected file content')`.","cause":"Forgetting to provide initial data to `MockOpen` via the `read_data` argument when mocking a file read operation.","error":"AssertionError: Expected 'some_data', but received '' (empty string) or 'None'"},{"fix":"Ensure `read_data` and any data passed to `f.write()` match the expected type for the file mode. For binary modes (`'rb'`, `'wb'`), use `b\"...\"` for bytes. For text modes (`'r'`, `'w'`), use `\"...\"` for strings.","cause":"Mismatch between the file mode (e.g., 'rb' for binary, 'r' for text) and the type of data provided (`read_data`) or written to the mock file. For binary modes, `read_data` and `write` arguments must be `bytes`; for text modes, they must be `str`.","error":"TypeError: a bytes-like object is required, not 'str'"}]}