In a subclass of QFileDialog there is a method, on_dir_entered, which should be called when the QFileDialog's signal directoryEntered fires, thus:
self.directoryEntered.connect(self.on_dir_entered)
The problem is that a signal takes a non-negligible time to take effect. Originally I was inspired by this answer by eyllanesc, a notable PyQt5 expert. With an isolated test this sort of technique using QTimer.singleShot() can work, although I had vague doubts about it from the beginning. And indeed, it turns out on my machine that I get "test leakage" with this sort of thing, particularly when there is more than one such test method: strange errors apparently occurring outside the tests themselves:
TEARDOWN ERROR: Exceptions caught in Qt event loop:
... so I went back to the pytest-qt docs and found that there are various methods available beginning wait... seemingly to cater to the problem of signals or other events taking a non-negligible time to have effect.  So I made a few tries to test signal directoryEntered:
def test_directoryEntered_triggers_on_dir_entered(request, qtbot, tmpdir):
    project = mock.Mock()
    project.main_window = QtWidgets.QWidget()
    project.home_dir_path = pathlib.Path(str(tmpdir))
    fd = save_project_dialog_class.SaveProjectDialog(project)
    with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
        fd.directoryEntered.emit('dummy')
    qtbot.waitSignal(fd.directoryEntered, timeout=1000)
    mock_entered.assert_called_once()
and then
def test_directoryEntered_triggers_on_dir_entered(qtbot, tmpdir):
    project = mock.Mock()
    project.main_window = QtWidgets.QWidget()
    project.home_dir_path = pathlib.Path(str(tmpdir))
    fd = SaveProjectDialog(project)
    qtbot.waitSignal(fd.directoryEntered, timeout=1000)
    with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
        fd.directoryEntered.emit('dummy')
    mock_entered.assert_called_once()
and then
def test_directoryEntered_triggers_on_dir_entered(qtbot, tmpdir):
    project = mock.Mock()
    project.main_window = QtWidgets.QWidget()
    project.home_dir_path = pathlib.Path(str(tmpdir))
    fd = SaveProjectDialog(project)
    with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
        fd.directoryEntered.emit('dummy')
    qtbot.wait(1000)
    mock_entered.assert_called_once()
All fail: the method is called 0 times.
I also tried:
def test_directoryEntered_triggers_on_dir_entered(qtbot, tmpdir):
    project = mock.Mock()
    project.main_window = QtWidgets.QWidget()
    project.home_dir_path = pathlib.Path(str(tmpdir))
    fd = SaveProjectDialog(project)
    with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
            fd.directoryEntered.emit('dummy')
    def check_called():
        mock_entered.assert_called_once()
    qtbot.waitUntil(check_called)
... this times out (default 5000 ms). I have double-checked and triple-checked that the code setting up connect on this signal is executed.
Later
By putting a print statement in the called slot (on_dir_entered) I now see what the problem is: despite the with mock.patch... line, the method is not being mocked!
At my low level of knowledge of mocking etc. I am tending to assume that this is because of the fact of using a signal with emit() to trigger the event: I can't think of another explanation.
NB this signal is fired "naturally" by one or two events in a QFileDialog (such as clicking the "go to parent directory" QToolButton). Maybe you have to do it that way... So I tried this:
def test_directoryEntered_triggers_on_dir_entered(request, qtbot, tmpdir):
    project = mock.Mock()
    project.main_window = QtWidgets.QWidget()
    project.home_dir_path = pathlib.Path(str(tmpdir))
    fd = save_project_dialog_class.SaveProjectDialog(project)
    to_parent_button = fd.findChild(QtWidgets.QToolButton, 'toParentButton')
    print(f'qtbot {qtbot} type(qtbot) {type(qtbot)}')
    with mock.patch.object(SaveProjectDialog, 'on_dir_entered') as mock_entered:
        qtbot.mouseClick(to_parent_button, QtCore.Qt.LeftButton)
    def check_called():
        mock_entered.assert_called_once()
    qtbot.waitUntil(check_called, timeout=1000)
Time out. 0 calls. Again I was able to ascertain that the real method is being called, and the patch is not working.
What am I doing wrong and is there a way to test this with something from pytest-qt?