What is the correct way to use pytest mocker
to patch a function?
I have installed pytest-mock
and am trying to use the mocker
fixture to patch a function, but I am getting the error "TypeError: Need a valid target to patch. You supplied 'return a + b'"
.
Here is the code I am working with:
# test_capitalize.py
import time
def sum(a, b):
time.sleep(10)
return a + b
def test_sum(mocker):
mocker.patch('return a + b') # This is where I get the error
assertEqual(sum(2, 3), 9)
Can you help me understand how to correctly use pytest mocker
to patch the sum
function and avoid this error?
I’ve worked with pytest mocker
quite a bit, and the key to using it correctly is ensuring you’re patching the right function with the correct path. Here’s a simple example of patching with return_value
to override a function’s output:
Patching with a return_value
to Simulate a Fixed Result:
You can make a function return a fixed value, regardless of its input:
import pytest
def sum(a, b):
return a + b
def test_sum1(mocker):
mocker.patch(__name__ + ".sum", return_value=9)
assert sum(2, 3) == 9 # This will pass because 'sum' always returns 9 now
Here, pytest mocker
ensures sum()
always returns 9
, making the test predictable.
@joe-elmoufak nailed the basics! But sometimes, you need more flexibility than a fixed return value. That’s where side_effect
comes in.
Patching with a side_effect
to Change Function Behavior Dynamically:
Instead of returning a fixed value, you can provide a custom function to control behavior:
def test_sum2(mocker):
def crazy_sum(a, b):
return b + b # A different behavior, summing only 'b'
mocker.patch(__name__ + ".sum", side_effect=crazy_sum)
assert sum(2, 3) == 6 # This will pass because the new behavior sums 'b + b'
Now, pytest mocker
replaces sum()
with crazy_sum()
, changing the behavior dynamically. Super useful for simulating complex logic!
Great points so far! But what if you’re testing code that interacts with an external API or service? You don’t want tests to depend on real API calls, so let’s patch an external function instead.
Using pytest mocker
to Patch an External Function (for APIs & Services):
import requests
import pytest
def get_weather(city):
response = requests.get(f"https://api.weather.com/{city}")
return response.json()
def test_weather(mocker):
mock_response = mocker.Mock()
mock_response.json.return_value = {"temperature": 72}
# Patching 'requests.get' to return our mock response
mocker.patch('requests.get', return_value=mock_response)
weather = get_weather("New York")
assert weather["temperature"] == 72 # Test runs without hitting the actual API
This is a lifesaver when dealing with APIs. pytest mocker
ensures your tests are isolated and fast!