Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I patch the `pathlib.Path.exists()` method?

I want to patch the exists() method of a pathlib.Path object for a unit test but I have problems getting this to work.

What I am trying to do is this:

from unittest.mock import patch
from pathlib import Path

def test_move_basic():
    p = Path('~/test.py')
    with patch.object(p, 'exists') as mock_exists:
        mock_exists.return_value = True

But it fails with:

AttributeError: 'PosixPath' object attribute 'exists' is read-only.

Any ideas?

like image 855
tfeldmann Avatar asked Feb 19 '18 10:02

tfeldmann


People also ask

How does path from Pathlib work?

With pathlib , file paths can be represented by proper Path objects instead of plain strings as before. These objects make code dealing with file paths: Easier to read, especially because / is used to join paths together. More powerful, with most necessary methods and properties available directly on the object.

Should I use Pathlib or os path?

With Pathlib, you can do all the basic file handling tasks that you did before, and there are some other features that don't exist in the OS module. The key difference is that Pathlib is more intuitive and easy to use. All the useful file handling methods belong to the Path objects.

Does Pathlib exist?

pathlib. Path. exists() method is used to check whether the given path points to an existing file or directory or not.

What is the use of Pathlib module in Python?

New in version 3.4. This module offers classes representing filesystem paths with semantics appropriate for different operating systems.


1 Answers

You need to patch the class, not the instance. It is enough to patch the method on the Path class, as it defines the exists method for the whole of the pathlib library (PosixPath, WindowsPath, PurePosixPath and PureWindowsPath all inherit the implementation):

>>> from unittest.mock import patch
>>> from pathlib import Path
>>> p = Path('~/test.py')
>>> with patch.object(Path, 'exists') as mock_exists:
...     mock_exists.return_value = True
...     p.exists()
...
True
>>> with patch.object(Path, 'exists') as mock_exists:
...     mock_exists.return_value = False
...     p.exists()
...
False
>>> with patch.object(Path, 'exists') as mock_exists:
...     mock_exists.return_value = 'Anything you like, actually'
...     p.exists()
...
'Anything you like, actually'

The pathlib classes use __slots__ to keep their memory footprint low, which has the side-effect of their instances not supporting arbitrary attribute assignment.

like image 185
Martijn Pieters Avatar answered Sep 21 '22 05:09

Martijn Pieters