0

So, I am trying to mock some API's in my class, the code looks something like this.

import requests
class myclass:
  def A(self, data):
    response = requests.get("some_url", params)
    if response.data["has_value"]:
      new_response = requests.get("some_url", params)
      **do some validation on data recieved**
  def B(self, data):
    response = requests.get("some_url", params)
    **do some validation on data recieved**
  def _run(self):
    **some code**
    self.A(data)
    self.B(data)

m = myclass()
m.run()

I am trying to test for these and need some help with it. while doing validations we change some fields in data, and I have to verify if the data is correct. how can this be done? Thank you.

Lin Du
  • 88,126
  • 95
  • 281
  • 483
  • Which will be the functions under test? What do you want to mock? Why do you want to mock it? What have you tried so far? – OregonTrail Mar 29 '20 at 05:46
  • the run function will be under test. I want to mock the api's. I want to mock the apis inorder to reduce the api usage. i have tried using the mock module but i am not sure how. to mock multiple get calls. – Aditya Powale Mar 29 '20 at 07:33
  • I see! You want to mock `requests.get`? See this answer. https://stackoverflow.com/a/28507806/384954 The most important thing here is `@mock.patch('requests.get', side_effect=mocked_requests_get)` as a decorator on your _test function_ – OregonTrail Mar 29 '20 at 07:38
  • Does this answer your question? [How can I mock requests and the response?](https://stackoverflow.com/questions/15753390/how-can-i-mock-requests-and-the-response) – OregonTrail Mar 29 '20 at 07:39
  • how will the side effect work in my case? in `stackoverflow.com/a/28507806/384954` we are providing urls to fetchJson function but how will i distinguish between the get requests? – Aditya Powale Mar 29 '20 at 07:47
  • Notice that inside `mocked_requests_get` the urls are being distinguished, and different fake responses are sent based on that. `@mock.patch` is patching all instances of `requests.get` in the entire call stack for the test. – OregonTrail Mar 29 '20 at 07:57
  • 1
    Thank you so much for the response. Was able to do what i intended. – Aditya Powale Mar 29 '20 at 17:20

1 Answers1

0

Here is the unit test solution using unittest package of Python 3.7.5:

myclass.py:

import requests


class MyClass:
    def A(self, data):
        params = None
        response = requests.get("some_url", params)
        if response.data["has_value"]:
            new_response = requests.get("some_url", params)
            print(new_response)

    def B(self, data):
        params = None
        response = requests.get("some_url", params)

    def _run(self):
        data = {}
        self.A(data)
        self.B(data)

test_myclass.py:

import unittest
from myclass import MyClass, requests
from unittest.mock import MagicMock, patch
from collections import namedtuple


class testMyClass(unittest.TestCase):

    @patch('builtins.print')
    @patch.object(requests, 'get')
    def test_A(self, mocked_get, mocked_print):
        Response = namedtuple('Response', ['data'])
        response = Response(data={'has_value': True})
        mocked_get.side_effect = [response, 'new response']
        myclass = MyClass()
        data = {}
        myclass.A(data)
        mocked_get.assert_called_with('some_url', None)
        self.assertEqual(mocked_get.call_count, 2)
        mocked_print.assert_called_with('new response')

    def test_B(self):
        # same as test_A, you can do it.
        self.assertEqual(1, 1)

    def test__run(self):
        myclass = MyClass()
        myclass.A = MagicMock()
        myclass.B = MagicMock()
        myclass._run()
        myclass.A.assert_called_with({})
        myclass.B.assert_called_with({})


if __name__ == '__main__':
    unittest.main()

unit test results with coverage report:

...
----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK
Name                                         Stmts   Miss  Cover   Missing
--------------------------------------------------------------------------
src/stackoverflow/60910413/myclass.py           15      2    87%   13-14
src/stackoverflow/60910413/test_myclass.py      27      0   100%
--------------------------------------------------------------------------
TOTAL                                           42      2    95%
Lin Du
  • 88,126
  • 95
  • 281
  • 483