Как смоделировать метод, который использует request.get в моем классе?

Я пытаюсь создать несколько модульных тестов для своего класса. Я хочу издеваться над ними, чтобы не сжечь свою квоту API, выполняя некоторые из этих тестов. У меня есть несколько тестовых случаев, которые будут вызывать метод fetch, и в зависимости от переданного URL-адреса я получу разные результаты.

Мой пример класса выглядит так:

import requests
class ExampleAPI(object):
    def fetch(self, url, params=None, key=None, token=None, **kwargs):
        return requests.get(url).json() # Returns a JSON string

учебник, который я смотрю на выставках что я могу сделать что-то вроде этого:

import unittest
from mock import patch

def fake_fetch_test_one(url):
    ...

class TestExampleAPI(unittest.TestCase):
    @patch('mymodule.ExampleAPI.fetch', fake_fetch_test_one)
    def test_fetch(self):
        e = ExampleAPI()
        self.assertEqual(e.fetch('http://my.api.url.example.com'), """{'result': 'True'}""")

Однако, когда я это делаю, я получаю сообщение об ошибке:

TypeError: fake_fetch_test_one() takes exactly 1 argument (3 given)

Как правильно издеваться над вызовом requests.get, который находится в методе моего класса? Мне понадобится возможность изменить фиктивный ответ для каждого теста, потому что разные URL-адреса могут предоставлять разные типы ответов.


person NewGuy    schedule 01.03.2016    source источник


Ответы (2)


Ваша поддельная выборка должна принимать те же аргументы, что и оригинал:

def fake_fetch(self, url, params=None, key=None, token=None, **kwargs):

Обратите внимание, что лучше издеваться только над внешним интерфейсом, что означает позволить fetch вызывать requests.get (или, по крайней мере, то, что он считает requests.get):

@patch('mymodule.requests.get')
def test_fetch(self, fake_get):
    # It would probably be better to just construct
    # a valid fake response object whose `json` method
    # would return the right thing, but this is a easier
    # for demonstration purposes. I'm assuming nothing else
    # is done with the response.
    expected = {"result": "True"}
    fake_get.return_value.json.return_value = expected
    e = ExampleAPI()
    self.assertEqual(e.fetch('http://my.api.url.example.com'), expected)
person chepner    schedule 01.03.2016

из вашего тестового метода вы можете обезьяны исправлять свой модуль запросов

import unittest

class Mock:
   pass

ExampleAPI.requests = Mock()

def fake_get_test_one(url):
    /*returns fake get json */

ExampleAPI.requests.get= Mock()
ExampleAPI.requests.json = fake_get_test_one

class TestExampleAPI(unittest.TestCase):

    def test_fetch(self):
        e = ExampleAPI()
        self.assertEqual(e.fetch('http://my.api.url.example.com'), """{'result': 'True'}""")

вы можете установить патч в каждом методе setup() и соответствующих методах teardown() вашего тестового класса, если это необходимо.

person maazza    schedule 01.03.2016
comment
Не нужно изобретать собственную систему насмешек; OP использует библиотеку mock. - person chepner; 01.03.2016