Search code examples
pythonpython-unittest

How to mock pathlib.Path.read_text for a particular file


The unittest docs show you how to use mock_open to mock direct calls to builtins.open.

But how about mocking pathlib's read_text like this:

import pathlib

pathlib.Path("/path/to/file").read_text()

Using the recipe in the unittest docs doesn't patch this correctly? It must use builtins.open under the hood somewhere but where??


Solution

  • You can patch pathlib.Path.read_text directly. You only need to keep a reference to the original method, so you can decide whether to return a "fake" value, or execute the original method.

    import pathlib
    from unittest.mock import patch
    
    
    path_to_mock = "foo/bar"
    original_read_text = pathlib.Path.read_text
    
    def read_text_side_effect(self: pathlib.Path, *args, **kwargs):
        # how you compare the paths depends on your use case.
        if self.absolute() == pathlib.Path(path_to_mock).absolute():
            return "mocked text"
        else:
            return original_read_text(self, *args, **kwargs)
    
    with patch("pathlib.Path.read_text", autospec=True) as mock_read:
        mock_read.side_effect = read_text_side_effect
    
        print(pathlib.Path(path_to_mock).read_text())
        print(pathlib.Path("real_file").read_text())
    

    Assuming "real_file" exists, you should see "mocked text" and the file's content in the output.