3

I am trying to mock the call to a function and still have the effect of the function apply. I found the solution using Python wraps, but all examples I found are applied to mocking the member method of a class. In my case, I have a pure function (not defined in a class). This seems to not work with the usual examples, as they require you to instantiate the class first I guess to obtain the real version of the method to pass into wraps.

Can this be done with pure functions? https://wesmckinney.com/blog/spying-with-python-mocks/

My code:

<this_module.py>

def my_function:
  does something important

def test_my_function:
  with patch.object("this_module", "my_function", wraps="this_module.my_function")
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92

1 Answers1

0

From my own attempts to solve a similar problem - you cannot use spy on a pure function, you can only spy on a specific object's method. The best you could do is wrap my_function in a dummy class, and pass an instance of that class anywhere.

Using pytest-mock:

from pytest_mock import MockerFixture

def my_function(**kwargs):
  # does something important

class MyWrapperClass:
  def wrap_my_function(**wkargs):
    return my_function(kwargs)

def my_other_function(wrapper: MyWrapperClass):
  # do a bunch of stuff
  results = wrapper.wrap_my_function(foo='bar')
  # do more stuff
  return final_results

def test_my_function(mocker: MockerFixture):
  my_wrapper = MyWrapperClass()
  spy_my_function = mocker.spy(my_wrapper, 'wrap_my_function')
  results = my_other_function(my_wrapper)
  assert results is not None
  assert spy_my_function.call_count == 1

Alternatively if you don't actually care about calling my_function() so much as you care about making sure the results are what you need them to be:

from pytest_mock import MockerFixture
def my_function(**kwargs):
  does something important

def my_other_function():
  # do a bunch of stuff
  results = my_function(foo='bar')
  # do more stuff
  return final_results

test_my_other_function(mocker: MockerFixture):
  mock_my_function = mocker.patch("this_module.my_function", return_value={'foo': 'bar'})
  results = my_other_function()
  assert mock_my_function.call_count == 1
  assert results is not None
  
Max
  • 666
  • 1
  • 6
  • 23