Cam
Cam

Reputation: 1731

Pytest mock using decorator to mock function containing context manager return value not passed

So I am struggling with mocking this function due to the context manager.

Function under test

import fitz

def with_test_func(next_pdfs_path):
    text = ''
    with fitz.open(next_pdfs_path) as doc:
        text = doc
    return text

Test code

@mock.patch("content_production.fitz.open.__enter__", return_value='value_out')
def test_with_test_func(mock_fitz_open):
    assert cp.with_test_func('value_in') == 'value_out'

Error

RuntimeError: cannot open value_in: No such file or directory

I have tested this without the context manager and it works. So how would I fix this? thanks

Edit

So as suggested by @MrBean I tried this

@mock.patch("content_production.fitz.open.return_value.__enter__", return_value='value_out')
def test_with_test_func(mock_fitz_open):
    assert cp.with_test_func('value_in') == 'value_out'

It gives me this error

thing = <class 'fitz.fitz.Document'>, comp = 'return_value', import_path = 'content_production.fitz.open.return_value'

    def _dot_lookup(thing, comp, import_path):
        try:
            return getattr(thing, comp)
        except AttributeError:
>           __import__(import_path)
E           ModuleNotFoundError: No module named 'content_production.fitz'; 'content_production' is not a package

Upvotes: 0

Views: 980

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16815

The problem is that return_value is a property of the mock, not of the patched function, so you cannot put it into the patch argument string. Instead, you have to set the return value on the mock for the open method:

@mock.patch("content_production.fitz.open")
def test_with_test_func(mock_fitz_open):
    mock_fitz_open.return_value.__enter__.return_value = 'value_out'
    assert cp.with_test_func('value_in') == 'value_out'

Upvotes: 2

Related Questions