Test module for python application using query library

I am writing an application that performs REST operations using Kenneth Reitz asks for a library , and I struggle to find a good way to unit test these applications, because the queries provide their methods using module level methods.

What I want is the ability to synthesize a conversation between two parties; Provide a series of statement and response requests.

+46
python unit-testing testing mocking python-requests
Mar 04 '12 at 23:40
source share
5 answers

If you use custom queries, try httmock . It is wonderfully simple and elegant:

from httmock import urlmatch, HTTMock import requests # define matcher: @urlmatch(netloc=r'(.*\.)?google\.com$') def google_mock(url, request): return 'Feeling lucky, punk?' # open context to patch with HTTMock(google_mock): # call requests r = requests.get('http://google.com/') print r.content # 'Feeling lucky, punk?' 

If you want something more general (like mocking a library using http calls, for example ), go to httpretty .

Almost as elegant:

 import requests import httpretty @httpretty.activate def test_one(): # define your patch: httpretty.register_uri(httpretty.GET, "http://yipit.com/", body="Find the best daily deals") # use! response = requests.get('http://yipit.com') assert response.text == "Find the best daily deals" 

HTTPretty is much more functional - it also offers a mocking status code, streaming responses, rotating responses, dynamic responses (with a callback).

+35
Aug 28 '13 at 14:19
source share

You can use a mocking library like Mocker to intercept calls in the query library and return the specified results.

As a very simple example, consider this class that uses a query library:

 class MyReq(object): def doSomething(self): r = requests.get('https://api.github.com', auth=('user', 'pass')) return r.headers['content-type'] 

Here is a unit test, which intercepts the requests.get call and returns the specified result for testing:

 import unittest import requests import myreq from mocker import Mocker, MockerTestCase class MyReqTests(MockerTestCase): def testSomething(self): # Create a mock result for the requests.get call result = self.mocker.mock() result.headers self.mocker.result({'content-type': 'mytest/pass'}) # Use mocker to intercept the call to requests.get myget = self.mocker.replace("requests.get") myget('https://api.github.com', auth=('user', 'pass')) self.mocker.result(result) self.mocker.replay() # Now execute my code r = myreq.MyReq() v = r.doSomething() # and verify the results self.assertEqual(v, 'mytest/pass') self.mocker.verify() if __name__ == '__main__': unittest.main() 

When I run this unit test, I get the following result:

 . ---------------------------------------------------------------------- Ran 1 test in 0.004s OK 
+19
Mar 05 2018-12-12T00:
source share

Actually, it’s a little strange that the library has a blank page about testing end-user modules, focusing on usability and ease of use. However, Dropbox's easy-to-use library is not surprisingly called responses . Here is his opening post . It states that they did not use httpretty without specifying the reason for the failure and writing a library with a similar API.

 import unittest import requests import responses class TestCase(unittest.TestCase): @responses.activate def testExample(self): responses.add(**{ 'method' : responses.GET, 'url' : 'http://example.com/api/123', 'body' : '{"error": "reason"}', 'status' : 404, 'content_type' : 'application/json', 'adding_headers' : {'X-Foo': 'Bar'} }) response = requests.get('http://example.com/api/123') self.assertEqual({'error': 'reason'}, response.json()) self.assertEqual(404, response.status_code) 
+17
Nov 22 '14 at 13:02
source share

using mocker as in srgerg answer:

 def replacer(method, endpoint, json_string): from mocker import Mocker, ANY, CONTAINS mocker = Mocker() result = mocker.mock() result.json() mocker.count(1, None) mocker.result(json_string) replacement = mocker.replace("requests." + method) replacement(CONTAINS(endpoint), params=ANY) self.mocker.result(result) self.mocker.replay() 

For the request library, this will lead to the interception of the request by the method and endpoint that you click, and replace .json () with the response sent by json_string.

+2
May 12 '13 at 2:46
source share

The absence of these request-mock responses.

On the page:

 >>> import requests >>> import requests_mock 

As a context manager:

 >>> with requests_mock.mock() as m: ... m.get('http://test.com', text='data') ... requests.get('http://test.com').text ... 'data' 

Or as a decorator:

 >>> @requests_mock.mock() ... def test_func(m): ... m.get('http://test.com', text='data') ... return requests.get('http://test.com').text ... >>> test_func() 'data' 
0
Jun 24 '17 at 10:48
source share



All Articles