requests-mock/requests_mock/tests/test_mocker.py

412 lines
14 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
import requests
import requests_mock
from requests_mock import exceptions
from requests_mock import response
from requests_mock.tests import base
original_send = requests.Session.send
class MockerTests(base.TestCase):
def assertMockStarted(self):
self.assertNotEqual(original_send, requests.Session.send)
def assertMockStopped(self):
self.assertEqual(original_send, requests.Session.send)
def _do_test(self, m):
self.assertMockStarted()
matcher = m.register_uri('GET', 'http://www.test.com', text='resp')
resp = requests.get('http://www.test.com')
self.assertEqual('resp', resp.text)
return matcher
def test_multiple_starts(self):
mocker = requests_mock.Mocker()
self.assertMockStopped()
mocker.start()
self.assertMockStarted()
self.assertRaises(RuntimeError, mocker.start)
mocker.stop()
self.assertMockStopped()
mocker.stop()
def test_with_context_manager(self):
self.assertMockStopped()
with requests_mock.Mocker() as m:
self._do_test(m)
self.assertMockStopped()
@mock.patch('requests.adapters.HTTPAdapter.send')
@requests_mock.mock(real_http=True)
def test_real_http(self, real_send, mocker):
url = 'http://www.google.com/'
test_text = 'real http data'
test_bytes = test_text.encode('utf-8')
# using create_response is a bit bootstrappy here but so long as it's
# coming from HTTPAdapter.send it's ok
req = requests.Request(method='GET', url=url)
real_send.return_value = response.create_response(req.prepare(),
status_code=200,
content=test_bytes)
resp = requests.get(url)
self.assertEqual(1, real_send.call_count)
self.assertEqual(url, real_send.call_args[0][0].url)
self.assertEqual(test_text, resp.text)
self.assertEqual(test_bytes, resp.content)
@requests_mock.mock()
def test_with_test_decorator(self, m):
self._do_test(m)
@requests_mock.mock(kw='mock')
def test_with_mocker_kwargs(self, **kwargs):
self._do_test(kwargs['mock'])
def test_with_decorator(self):
@requests_mock.mock()
def inner(m):
self.assertMockStarted()
self._do_test(m)
self.assertMockStopped()
inner()
self.assertMockStopped()
def test_with_class_decorator(self):
outer = self
@requests_mock.mock()
class Decorated(object):
def test_will_be_decorated(self, m):
outer.assertMockStarted()
outer._do_test(m)
def will_not_be_decorated(self):
outer.assertMockStopped()
decorated_class = Decorated()
self.assertMockStopped()
decorated_class.test_will_be_decorated()
self.assertMockStopped()
decorated_class.will_not_be_decorated()
self.assertMockStopped()
def test_with_class_decorator_and_custom_kw(self):
outer = self
@requests_mock.mock(kw='custom_m')
class Decorated(object):
def test_will_be_decorated(self, **kwargs):
outer.assertMockStarted()
outer._do_test(kwargs['custom_m'])
def will_not_be_decorated(self):
outer.assertMockStopped()
decorated_class = Decorated()
self.assertMockStopped()
decorated_class.test_will_be_decorated()
self.assertMockStopped()
decorated_class.will_not_be_decorated()
self.assertMockStopped()
@mock.patch.object(requests_mock.mock, 'TEST_PREFIX', 'foo')
def test_with_class_decorator_and_custom_test_prefix(self):
outer = self
@requests_mock.mock()
class Decorated(object):
def foo_will_be_decorated(self, m):
outer.assertMockStarted()
outer._do_test(m)
def will_not_be_decorated(self):
outer.assertMockStopped()
decorated_class = Decorated()
self.assertMockStopped()
decorated_class.foo_will_be_decorated()
self.assertMockStopped()
decorated_class.will_not_be_decorated()
self.assertMockStopped()
@requests_mock.mock()
def test_query_string(self, m):
url = 'http://test.url/path'
qs = 'a=1&b=2'
m.register_uri('GET', url, text='resp')
resp = requests.get("%s?%s" % (url, qs))
self.assertEqual('resp', resp.text)
self.assertEqual(qs, m.last_request.query)
self.assertEqual(['1'], m.last_request.qs['a'])
self.assertEqual(['2'], m.last_request.qs['b'])
@requests_mock.mock()
def test_mock_matcher_attributes(self, m):
matcher = self._do_test(m)
self.assertEqual(1, matcher.call_count)
self.assertEqual(1, m.call_count)
self.assertTrue(matcher.called)
self.assertTrue(matcher.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
self.assertEqual(m.request_history, matcher.request_history)
self.assertIs(m.last_request, matcher.last_request)
def test_copy(self):
mocker = requests_mock.mock(kw='foo', real_http=True)
copy_of_mocker = mocker.copy()
self.assertIsNot(copy_of_mocker, mocker)
self.assertEqual(copy_of_mocker._kw, mocker._kw)
self.assertEqual(copy_of_mocker._real_http, mocker._real_http)
class MockerHttpMethodsTests(base.TestCase):
URL = 'http://test.com/path'
TEXT = 'resp'
def assertResponse(self, resp):
self.assertEqual(self.TEXT, resp.text)
@requests_mock.Mocker()
def test_mocker_request(self, m):
method = 'XXX'
mock_obj = m.request(method, self.URL, text=self.TEXT)
resp = requests.request(method, self.URL)
self.assertResponse(resp)
self.assertTrue(mock_obj.called)
self.assertTrue(mock_obj.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
@requests_mock.Mocker()
def test_mocker_get(self, m):
mock_obj = m.get(self.URL, text=self.TEXT)
self.assertResponse(requests.get(self.URL))
self.assertTrue(mock_obj.called)
self.assertTrue(mock_obj.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
@requests_mock.Mocker()
def test_mocker_options(self, m):
mock_obj = m.options(self.URL, text=self.TEXT)
self.assertResponse(requests.options(self.URL))
self.assertTrue(mock_obj.called)
self.assertTrue(mock_obj.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
@requests_mock.Mocker()
def test_mocker_head(self, m):
mock_obj = m.head(self.URL, text=self.TEXT)
self.assertResponse(requests.head(self.URL))
self.assertTrue(mock_obj.called)
self.assertTrue(mock_obj.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
@requests_mock.Mocker()
def test_mocker_post(self, m):
mock_obj = m.post(self.URL, text=self.TEXT)
self.assertResponse(requests.post(self.URL))
self.assertTrue(mock_obj.called)
self.assertTrue(mock_obj.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
@requests_mock.Mocker()
def test_mocker_put(self, m):
mock_obj = m.put(self.URL, text=self.TEXT)
self.assertResponse(requests.put(self.URL))
self.assertTrue(mock_obj.called)
self.assertTrue(mock_obj.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
@requests_mock.Mocker()
def test_mocker_patch(self, m):
mock_obj = m.patch(self.URL, text=self.TEXT)
self.assertResponse(requests.patch(self.URL))
self.assertTrue(mock_obj.called)
self.assertTrue(mock_obj.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
@requests_mock.Mocker()
def test_mocker_delete(self, m):
mock_obj = m.delete(self.URL, text=self.TEXT)
self.assertResponse(requests.delete(self.URL))
self.assertTrue(mock_obj.called)
self.assertTrue(mock_obj.called_once)
self.assertTrue(m.called)
self.assertTrue(m.called_once)
@requests_mock.Mocker()
def test_mocker_real_http_and_responses(self, m):
self.assertRaises(RuntimeError,
m.get,
self.URL,
text='abcd',
real_http=True)
@requests_mock.Mocker()
def test_mocker_real_http(self, m):
data = 'testdata'
uri1 = 'fake://example.com/foo'
uri2 = 'fake://example.com/bar'
uri3 = 'fake://example.com/baz'
m.get(uri1, text=data)
m.get(uri2, real_http=True)
self.assertEqual(data, requests.get(uri1).text)
# This should fail because requests can't get an adapter for mock://
# but it shows that it has tried and would have made a request.
self.assertRaises(requests.exceptions.InvalidSchema,
requests.get,
uri2)
# This fails because real_http is not set on the mocker
self.assertRaises(exceptions.NoMockAddress,
requests.get,
uri3)
# do it again to make sure the mock is still in place
self.assertEqual(data, requests.get(uri1).text)
@requests_mock.Mocker(case_sensitive=True)
def test_case_sensitive_query(self, m):
data = 'testdata'
query = {'aBcDe': 'FgHiJ'}
m.get(self.URL, text=data)
resp = requests.get(self.URL, params=query)
self.assertEqual('GET', m.last_request.method)
self.assertEqual(200, resp.status_code)
self.assertEqual(data, resp.text)
for k, v in query.items():
self.assertEqual([v], m.last_request.qs[k])
@mock.patch.object(requests_mock.Mocker, 'case_sensitive', True)
def test_global_case_sensitive(self):
with requests_mock.mock() as m:
data = 'testdata'
query = {'aBcDe': 'FgHiJ'}
m.get(self.URL, text=data)
resp = requests.get(self.URL, params=query)
self.assertEqual('GET', m.last_request.method)
self.assertEqual(200, resp.status_code)
self.assertEqual(data, resp.text)
for k, v in query.items():
self.assertEqual([v], m.last_request.qs[k])
def test_nested_mocking(self):
url1 = 'http://url1.com/path1'
url2 = 'http://url2.com/path2'
url3 = 'http://url3.com/path3'
data1 = 'data1'
data2 = 'data2'
data3 = 'data3'
with requests_mock.mock() as m1:
r1 = m1.get(url1, text=data1)
resp1a = requests.get(url1)
self.assertRaises(exceptions.NoMockAddress, requests.get, url2)
self.assertRaises(exceptions.NoMockAddress, requests.get, url3)
self.assertEqual(data1, resp1a.text)
# call count = 3 because there are 3 calls above, url 1-3
self.assertEqual(3, m1.call_count)
self.assertEqual(1, r1.call_count)
with requests_mock.mock() as m2:
r2 = m2.get(url2, text=data2)
self.assertRaises(exceptions.NoMockAddress, requests.get, url1)
resp2a = requests.get(url2)
self.assertRaises(exceptions.NoMockAddress, requests.get, url3)
self.assertEqual(data2, resp2a.text)
with requests_mock.mock() as m3:
r3 = m3.get(url3, text=data3)
self.assertRaises(exceptions.NoMockAddress,
requests.get,
url1)
self.assertRaises(exceptions.NoMockAddress,
requests.get,
url2)
resp3 = requests.get(url3)
self.assertEqual(data3, resp3.text)
self.assertEqual(3, m3.call_count)
self.assertEqual(1, r3.call_count)
resp2b = requests.get(url2)
self.assertRaises(exceptions.NoMockAddress, requests.get, url1)
self.assertEqual(data2, resp2b.text)
self.assertRaises(exceptions.NoMockAddress, requests.get, url3)
self.assertEqual(3, m1.call_count)
self.assertEqual(1, r1.call_count)
self.assertEqual(6, m2.call_count)
self.assertEqual(2, r2.call_count)
self.assertEqual(3, m3.call_count)
self.assertEqual(1, r3.call_count)
resp1b = requests.get(url1)
self.assertEqual(data1, resp1b.text)
self.assertRaises(exceptions.NoMockAddress, requests.get, url2)
self.assertRaises(exceptions.NoMockAddress, requests.get, url3)
self.assertEqual(6, m1.call_count)
self.assertEqual(2, r1.call_count)