preocess_video in workflow.py calls detect_objects() whose return_value is what I want to mock. But When I call process_video() in test_workflow.py I don't get the mocked return value, instead It actually call the detect_objects function.

How can I mock the return value of detect_objects when calling the parent function process_video

Directory Structure

.
├── __tests__
│   └── test_workflow.py
└── video_processor
    ├── __init__.py
    ├── detectors
    │   ├── __init__.py
    │   ├── object.py
    └── workflow.py

Workflow.py

def process_video(request: Request, config: Config):
    object_detections = detect_objects(request, config) # Want to mock the return value of detect_objects
    # Detect_objects call other function internally
    # More logic
    # Some more logic
    return data

test_workfkow.py

object_detections_dict == ... # sample data
def test_process_workflow(requests_mock, mocker):
    # Arrange
    request = Request(...)
    config = Config(...)
    
    # Mock some API calls
    requests_mock.post(...)
    requests_mock.post(...)
    
    with mocker.patch("video_processor.detectors.object.detect_objects") as mock:
         mock.return_value = object_detection_dict
         process_video(request, config)
    

Tried this as suggested in comments:

# test_workflow.py
object_detections_dict == ... # sample data dict

@pytest.fixture
def detect_objects_fixture(mocker: MockerFixture):
    mocker.patch("video_processor.detectors.object.detect_objects", return_value = object_detection_dict)

def test_process_workflow(requests_mock, detect_objects_fixture):
    # Arrange
    request = Request(...)
    config = Config(...)
    
    # Mock some API calls
    requests_mock.post(...)
    requests_mock.post(...)
    

    result = process_video(request, config)
    

1

There are 1 answers

3
Loïc Ribere On

Creating a fixture using pytest_mock and unitest.mock to patch the return value of a function


Exemple :

@pytest.fixture
def detect_objects_fixture(mocker):
    mocker.patch("path to the detect objects function", return_value = whatever you want)

Add detect_objects_fixture to the parameters of your test function, pytest should use the fixture to patch the return value of the function you targeted.

Here is an example :

import pytest
import unittest.mock
import pytest_mock.plugin



def process_video():
    object_detections = detect_objects()
    # Detect_objects call other function internally
    # More logic
    # Some more logic
    return object_detections

def detect_objects():
    return [1,2]

@pytest.fixture
def detect_objects_fixture(mocker):
    return mocker.patch("modulewhereitis.detect_objects", return_value=[3])

def test_process_video(detect_objects_fixture):
    assert process_video() == [3]

Output :

PASSED                                        [100%]

Documentation