Im trying to unittest some_function
which is MyClass
instance method that requires someapi.api
instance . How do I patch self.api.something1.something2(foo)
with some return value?
import someapi
class MyClass(object):
def __init__(self,a,b):
self.a = a
self.b = b
self.api = someapi.api(self.a, self.b)
def some_function(self, foo):
result = self.api.something1.something2(foo)
new_result = dosomething(result)
return new_result
So really what I want is to mock response of this api so I can test that dosomething(result)
does what I want.
@mock.patch('self.api.something1.something2', side_effect='something')
def testGet_circuits(self,pymock):
result = some_function('foobar')
expected_result= 'something'
self.assertEqual(result, 'expected_result')
I tried
@mock.patch('someapi.api')
def testSome_function(self,someapi_mock):
api = MyClass('a','b')
result = api.some_function('foo')
self.assertEqual(result,'newfoo')
What I'm strugling with is how to mock self.api.something1.something2(foo)
inside some_function :(
You are not setting up your mock properly. I crafted an example using your code and managed to put together a test method that works. Ultimately, what is happening here is that you are not telling your mocks how to behave when the code runs. You start off probably mocking in the right place, but beyond that, the mock itself no longer has any of the attributes you are trying to access in order to allow the code to run. I'll go through the code to help illustrate:
class TestStuff(unittest.TestCase):
@mock.patch('real_code.someapi.api', autospec=True)
def testSome_function(self, someapi_mock):
someapi_mock.return_value.something1 = mock.Mock(spec=Something)
someapi_mock.return_value.something1.something2.return_value = 'newfoo'
api = MyClass('a', 'b')
result = api.some_function('foo')
self.assertEqual(result, 'newfoo')
First thing, notice that I'm mocking more with respect to where I am testing, which is important to keep in mind, and you should read about here .
For the mock configuration issue, I can only assume from your real code, api.something1.something2
indicates that something1
is holding the instance of some other class that gives you access to the something2
method. So, the example is being illustrated with that assumption.
Now, as you can see within the first line of the method, what I'm doing is telling my mock to ensure it has the something1
attribute. It is important to remember that when you are mocking, and even when you set the spec and/or autospec (as I have used in my example), you don't get access to the attributes created in your __init__
. So you need to provide them in your mock per my example.
The second line now goes the next step to mock out the something2
method behaviour you are trying to get a result from. With this done, when your real code is called, it should go through the expected behaviour you set up and return the expected newfoo
value.
To further help, here is the exact code I used to help put together that functional test:
import someapi
class MyClass(object):
def __init__(self,a,b):
self.a = a
self.b = b
self.api = someapi.api(self.a, self.b)
def some_function(self, foo):
result = self.api.something1.something2(foo)
new_result = dosomething(result)
return new_result
def dosomething(foo):
return foo
class api:
def __init__(self, a, b):
self.a = a
self.b = b
self.something1 = Something()
class Something:
def something2(self, some_arg):
return some_arg
Thanks for all the answers definitely helped me I ended up doing below and worked like a charm . This whole mock thing looks like rabbit hole and i need to go deeper to fully understand.
@mock.patch('someapi.api')
def testSome_function(self,someapi_mock):
someapi_mock = return_value.something1.something2.return_value = 'mocked_value'
api = MyClass('a','b')
result = api.some_function('foo')
self.assertEqual(result,'newfoo')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.