I am testing a custom API in python that makes http requests, but I don't want to make a request to the real external system every time I run the unit tests. I am using python's mock library with a side_effect function to dynamically fake the API response. How do I get the side_effect method to behave like a class method?
import requests
class MyApiClass():
def make_request(self, params):
return requests.get('http://someurl.com', params=params)
def create_an_object(self, params):
return self.make_request(params)
import unittest, mock
def side_effect_func(self, params):
if params['name'] == 'Specific Name':
return {'text': 'Specific Action'}
else:
return {'text': 'General Action'}
class MyApiTest(unittest.TestCase):
def setUp(self):
super(MyApiTest, self).setUp()
mocked_method = mock.Mock(side_effect=side_effect_func)
MyApiClass.make_request = mocked_method
def test_create_object(self):
api = MyApiClass()
params = {'name': 'Specific Name'}
r = api.create_an_object(params) # Complains that two arguments are needed!
self.assertEqual(r['text'], 'Specific Action')
I get this error
TypeError: side_effect_func() takes exactly 2 arguments (1 given)
but I want side_effect_func
to pass api
as the first argument. Appreciate any help!
The simplest way would probably be to just make your mock method take a single argument, then reference MyApiClass
statically within the mock method itself. Otherwise, you could try mocking the class object itself (basically making a mock metaclass) or maybe using a factory that utilizes partial
to build a mock class method on the fly. But if the single argument/static reference method would work for you, that seems the best to me.
Also, from the Mock docs, there's mocking an unbound method using patch, which looks like it may be more what you need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With