def test_no_match_exception(self): pook.get('server.com/bar', reply=204) try: requests.get('http://server.com/baz') except Exception: pass else: raise RuntimeError('expected to fail')
def test_persistent(): pook.on() pook.get("https://www.example.com").persist().reply(200).json( {"data": True}) for counter in range(5): res = requests.get("https://www.example.com") assert res.json().get('data') pook.off()
def test_json_operator(should): with pook.use(): pook.get('foo.com', reply=200, response_json={'foo': 'bar'}) res = requests.get('http://foo.com') res | should.have.json.equal.to({'foo': 'bar'}) with pytest.raises(AssertionError): res | should.have.body('foo')
def test_body_operator(should): with pook.use(): pook.get('foo.com', reply=200, response_body='hello world') res = requests.get('http://foo.com') res | should.have.body.equal.to('hello world') with pytest.raises(AssertionError): res | should.have.body('foo')
def test_http_tutorial(): # Activate the HTTP mock engine pook.on() # Register a sample mock pook.get('server.org/foo?bar=baz', reply=200, response_headers={'Server': 'nginx'}, response_json={'foo': 'bar'}) # Perform HTTP request res = requests.get('http://server.org/foo?bar=baz') # Test response status to be OK res | should.be.ok # Or alternatively using the status code res | should.have.status(200) # Test request URL res | should.have.url.hostname('server.org') res | should.have.url.port(80) res | should.have.url.path('/foo') res | should.have.url.query.params({'bar': 'baz'}) # Test response body MIME content type res | should.have.content('json') # Test response headers (res | (should.have.header('Content-Type') .that.should.be.equal('application/json'))) res | should.have.header('Server').that.should.contain('nginx') # Test response body res | should.have.body.equal.to('{\n "foo": "bar"\n}') res | should.have.body.that.contains('foo') # Test response body length res | should.have.body.length.of(20) res | should.have.body.length.higher.than(10) # Test response JSON body res | should.have.json.equal.to({'foo': 'bar'}) res | should.have.json.have.key('foo') > should.be.equal.to('bar') # Validate response JSON bodies using JSONSchema res | should.implement.jsonschema({ '$schema': 'http://json-schema.org/draft-04/schema#', 'title': 'Response JSON', 'type': 'object', 'required': ['foo'], 'properties': { 'foo': { 'description': 'foo always means foo', 'type': 'string' } } })
async def test_refresh_token(): with pook.use(): # Populate token with request get_token_mock_1 = pook.post( 'https://foo.com/api/auth/v3/app_access_token/internal/', response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test' }) pook.get('https://foo.com/api/chat/v4/list').\ header('Authorization', 'Bearer test').\ reply(200).\ json({'code': 0, 'msg': 'OK', 'data': { 'groups': [ {'chat_id': 'chat_id_1', 'name': 'group_1'}, {'chat_id': 'chat_id_2', 'name': 'group_2'} ] }}) # Pass the first send text send_text_mock_1 = pook.post('https://foo.com/api/message/v4/send/', headers={'Authorization': 'Bearer test'}, response_json={ 'code': 0, 'msg': 'OK', 'data': {} }) # Fail the second send text with token expired send_text_mock_2 = pook.post('https://foo.com/api/message/v4/send/', headers={'Authorization': 'Bearer test'}, response_json={ 'code': 99991663, 'msg': 'token expired', }) # Feed the valid token get_token_mock_2 = pook.post( 'https://foo.com/api/auth/v3/app_access_token/internal/', response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test2' }) # System would try again send_text_mock_3 = pook.post('https://foo.com/api/message/v4/send/', headers={'Authorization': 'Bearer test2'}, response_json={ 'code': 0, 'msg': 'OK', 'data': {} }) bot = FeishuBot('foo', 'bar', 'https://foo.com/api') resp = await bot.send_text('hello world')
def test_url_protocol_operator(should): with pook.use(): pook.get('foo.com', reply=200, persist=True, response_type='json') requests.get('http://foo.com') | should.have.url.protocol('http') # Strict comparison # requests.get('http://foo.com') | should.have.url('http://foo.com/') with pytest.raises(AssertionError): requests.get('http://foo.com') | should.have.url('bar')
def test_header_presence(should): with pook.use(): pook.get('foo.com', reply=200, response_type='json') res = requests.get('http://foo.com') res | should.have.header('Content-Type') res | should.not_have.header('Server') with pytest.raises(AssertionError): res | should.have.header('Server')
def test_FUNC_call_WITH_responsive_url_EXPECT_call_successful() -> None: """ Check whether the call succeeded. :return: No return. """ with pook.use(): pook.get("https://example.com", status=200) status = HttpCall.call('GET', 'https://example.com').status assert status == 200
def test_pook_content_matching(): pook.on() pook.get("https://www.example.com").times(2).body("abc").reply(200).json( {"data": True}) res = requests.get("https://www.example.com", data="abc") assert res.json().get('data') with pytest.raises(Exception): requests.get("https://www.example.com", data="def") # Will throw once again pook.off()
def test_url_hostname_operator(should): with pook.use(): pook.get('foo.com', reply=200, persist=True, response_type='json') requests.get('http://foo.com') | should.have.url.hostname('foo.com') requests.get('http://foo.com') | should.have.url.hostname('foo', strict=False) with pytest.raises(AssertionError): requests.get('http://foo.com') | should.have.url('bar')
def test_body_match(should): with pook.use(): pook.get('foo.com', reply=200, response_body='hello world') res = requests.get('http://foo.com') res | should.have.body.to.match(r'(\w+) world$') res | should.have.body('hello world') pook.get('foo.com', reply=200, response_json={'foo': 'bar'}) res = requests.get('http://foo.com') res | should.have.body.json({'foo': 'bar'})
def test_FUNC_call_WITH_not_existing_endpoint_EXPECT_not_found() -> None: """ Check whether the call failed. :return: No return. """ with pook.use(): pook.get("https://example.com/does-not-exist", status=404) with pytest.raises(InternalError, match="Http call failed with status: 404."): HttpCall.call('GET', "https://example.com/does-not-exist")
def test_url_path_operator(should): with pook.use(): pook.get('foo.com', reply=200, persist=True, response_type='json') pook.get('foo.com/bar/baz', reply=200, persist=True, response_type='json') requests.get('http://foo.com/') | should.have.url.path('/') res = requests.get('http://foo.com/bar/baz') res | should.have.url.path('/bar/baz') res | should.have.url.path('baz', strict=False)
def test_pook_pending(): pook.on() pook.get("https://www.example.com").times(2).reply(200).json( {"data": True}) for counter in [1, 0]: res = requests.get("https://www.example.com") assert res.json().get('data') assert pook.pending() == counter with pytest.raises(Exception): # Will throw as there's no mocks res = requests.get("https://www.example.com") pook.off()
def test_url_port_operator(should): with pook.use(): pook.get('foo.com', reply=200, persist=True, response_type='json') pook.get('https://foo.com', reply=200, persist=True, response_type='json') requests.get('http://foo.com') | should.have.url.port(80) requests.get('http://foo.com:8080') | should.have.url.port(8080) requests.get('https://foo.com') | should.have.url.port(443) with pytest.raises(AssertionError): requests.get('http://foo.com') | should.have.url('bar')
def test_method_presence(should): with pook.use(): pook.get('foo.com', reply=200, response_type='json') res = requests.get('http://foo.com') res | should.have.method('GET') res | should.have.method.equal.to('get') res | should.have_not.method.equal.to('POST') with pytest.raises(AssertionError): res | should.have.method.equal.to('POST') with pytest.raises(AssertionError): res | should.have_not.method.equal.to('GET')
def test_search_on_github_cache_terraform_releases_does_not_cache_error_429( tmp_working_dir, terraform_releases_html_after_v0_13_0, # noqa: F811 ): # noqa: D103 with mock.patch("io.BytesIO", AutoclosingBytesIO): with pook.use(): repo = "hashicorp/terraform" releases_url = "https://github.com/{}/releases?after=v0.13.0".format( repo) # volatile mocks that can only be invoked once each pook.get( releases_url, reply=429, response_headers={ "Status": "429 Too Many Requests", "Date": formatdate(usegmt=True), "Retry-After": "120" }, times=1, ) pook.get( releases_url, reply=200, response_type="text/plain", response_body=terraform_releases_html_after_v0_13_0, response_headers={ "Status": "200 OK", "ETag": 'W/"df0474ebd25f223a95926ba58e11e77b"', "Cache-Control": "max-age=0, private, must-revalidate", "Date": formatdate(usegmt=True), }, times=1, ) patch_regex = r"[0-9]+(((-alpha|-beta|-rc)[0-9]+)|(?P<dev>-dev))?" # pook does not implement urllib3's retry logic so this first request will always return None during tests patch = tfwrapper.search_on_github(repo, "0.12", patch_regex, "14") assert patch is None patch = tfwrapper.search_on_github(repo, "0.12", patch_regex, "14") assert patch == "14" patch = tfwrapper.search_on_github(repo, "0.12", patch_regex, "") assert patch == "19" assert pook.isdone() assert not pook.pending_mocks() assert not pook.unmatched_requests()
def setup_fake_classroom_api( suffix_response_pairs: List[Tuple[str, str]]) -> Resource: """ Set up a fake Google Classroom/Admin SDK API using the pook HTTP traffic mocking library Parameters ---------- suffix_response_pairs: List[Tuple[str, str]] are pairs of endpoint suffixes and response jsons where endpoint suffixes are the suffixes of the endpoint being faked, for example: "courses" for the courses endpoint response jsons are the corresponding json response bodies to be returned. Returns ------- Resource a Google Classroom SDK Resource Notes ----- Requires pook to already be activated in a test """ fake_discovery_endpoint_json: str = Path( "tests/api/fake-classroom-discovery-endpoint.json").read_text() fake_credentials: Credentials = Credentials.from_service_account_file( "tests/api/fake-service-account.json", scopes=[], subject="*****@*****.**") pook.get( "http://www.googleapis.com:443/discovery/v1/apis/classroom/v1/rest", response_json=fake_discovery_endpoint_json, reply=200, ) pook.post( "http://oauth2.googleapis.com:443/token", response_json='{"access_token": "fake"}', reply=200, ) for suffix, response in suffix_response_pairs: pook.get( f"http://classroom.googleapis.com:443/v1/{suffix}", response_json=response, reply=200, ) return build("classroom", "v1", credentials=fake_credentials, cache_discovery=False)
def run(): pook.get('httpbin.org/ip', reply=403, response_headers={'pepe': 'lopez'}, response_json={'error': 'not found'}) res = requests.get('http://httpbin.org/ip') print('Status:', res.status_code) print('Headers:', res.headers) print('Body:', res.json()) print('Is done:', pook.isdone()) print('Pending mocks:', pook.pending_mocks()) print('Unmatched requests:', pook.unmatched_requests())
def test_kong_gateway_update_api(): pook.get('http://kong:8001/apis/test-api', reply=200, response_json={ 'created_at': 1540213698704, 'strip_uri': False, 'id': '6af8aa24-b520-471a-bced-942e6cc023b6', 'name': 'test-api', 'http_if_terminated': True, 'https_only': False, 'upstream_url': 'http://test.services.lan:8080', 'uris': [ '/test', '/api/test' ], 'preserve_host': False, 'upstream_connect_timeout': 60000, 'upstream_read_timeout': 60000, 'upstream_send_timeout': 60000, 'retries': 5 }) (pook.patch('http://kong:8001/apis/test-api').json({ 'name': 'test-api', 'uris': '/new,/new/test', 'upstream_url': 'http://new-test.services.lan:8089' }).reply(200).json({ 'created_at': 1540213698704, 'strip_uri': False, 'id': '6af8aa24-b520-471a-bced-942e6cc023b6', 'name': 'test-api', 'http_if_terminated': True, 'https_only': False, 'upstream_url': 'http://new-test.services.lan:8089', 'uris': [ '/new', '/new/test' ], 'preserve_host': False, 'upstream_connect_timeout': 60000, 'upstream_read_timeout': 60000, 'upstream_send_timeout': 60000, 'retries': 5 })) reg = KongGatewayRegistrator(gw_admin_url='http://kong:8001') resp = reg.register(name='test-api', host='new-test.services.lan', port=8089, paths=['/new', '/new/test']) assert resp is not None assert resp.get('uris') == ['/new', '/new/test'] assert resp.get('upstream_url') == 'http://new-test.services.lan:8089'
async def run(): pook.get('httpbin.org/ip', reply=403, response_headers={'pepe': 'lopez'}, response_json={'error': 'not found'}) async with aiohttp.ClientSession(loop=loop) as session: async with session.get('http://httpbin.org/ip') as res: print('Status:', res.status) print('Headers:', res.headers) print('Body:', await res.text()) print('Is done:', pook.isdone()) print('Pending mocks:', pook.pending_mocks()) print('Unmatched requests:', pook.unmatched_requests())
def test_FUNC_call_to_str_WITH_google_endpoint_EXPECT_successfull_call( ) -> None: """ Checks whether the http endpoint call to str sends request and receives a response. :return: No return. """ with pook.use(): pook.get('https://example.com') endpoint = HttpEndpoint( endpoint_url='https://example.com', method='GET', ) endpoint.call_to_str()
def setup_fake_reports_api(endpoint_suffix: str, response_json: str) -> Resource: """ Set up a fake Google Reports SDK API using the pook HTTP traffic mocking library Parameters ---------- endpoint_suffix: string is the suffix of the endpoint being faked, for example: "courses" for the courses endpoint response_json: string is the json response body to be returned Returns ------- Resource a Google Reports SDK Resource Notes ----- Requires pook to already be activated in a test """ fake_discovery_endpoint_json: str = Path( "tests/api/fake-admin-discovery-endpoint.json").read_text() fake_credentials: Credentials = Credentials.from_service_account_file( "tests/api/fake-service-account.json", scopes=[], subject="*****@*****.**") pook.get( "http://www.googleapis.com:443/discovery/v1/apis/admin/reports_v1/rest", response_json=fake_discovery_endpoint_json, reply=200, ) pook.post( "http://oauth2.googleapis.com:443/token", response_json='{"access_token": "fake"}', reply=200, ) pook.get( f"http://www.googleapis.com:443/admin/reports/v1/{endpoint_suffix}", response_json=response_json, reply=200, ) return build("admin", "reports_v1", credentials=fake_credentials, cache_discovery=False)
def test_header_value(should): with pook.use(): pook.get('foo.com', reply=200, response_type='json') res = requests.get('http://foo.com') res | should.have.header('Content-Type', 'application/json') (res | should.have.header('Content-Type') > should.be.equal('application/json')) with pytest.raises(AssertionError): res | should.have.header('Server', 'foo') with pytest.raises(AssertionError): res | should.have.header('Server')
def test_lookup_time_converts_non_actual_times(self): mock = pook.get(self.time_url, reply=200, response_json=TIMES_NONACTUAL) next_time = lookup_next_time('1538969940000', ROUTES[2], DIRS[1], STOPS[2], self.time_url_template) next_time | should.equal("22 Min")
def test_json_schema_operator(should): schema = { 'type': 'object', 'properties': { 'price': { 'type': 'number' }, 'name': { 'type': 'string' } } } with pook.use(): pook.get('foo.com').reply(200).json({'name': 'Eggs', 'price': 34.99}) res = requests.get('http://foo.com') res | should.satisfy.json_schema(schema)
def testDoesNotInterceptRequestWhenNoAuthorizationHeader(self): (pook.get('https://example.com/api/v1/valid/url').times(1).reply( 200).type('json').json({'status': 'ok'})) header_params_without_authorization = {'Accept': 'application/json'} res = self.a_get_request(header_params_without_authorization) self.assertTrue(pook.isdone()) self.assertEqual(res, {'status': 'ok'})
def test_json_complex(should): json = { 'foo': { 'foo': 123, 'bar': [{ 'baz': True }] }, 'bar': [1, 2, 3], 'baz': { 'foo': False } } with pook.use(): pook.get('foo.com', reply=200, response_json=json) res = requests.get('http://foo.com') res | should.have.json.equal.to(json)
def test_FUNC_call_WITH_not_existing_url_EXPECT_not_reached() -> None: """ Check whether the call failed. :return: No return. """ with pook.use(): mock = pook.get("https://unreachable.com").error(HTTPError()).persist() with pytest.raises(NotReachedError): HttpCall.call('GET', 'https://unreachable.com')
def test_pook_engine(): url = 'http://twitter.com/api/1/foobar' status = 404 response_json = {'error': 'foo'} mock = pook.get( url, headers={'content-type': 'application/json'}, reply=status, response_json=response_json, ) mock.persist() requests.get(url) assert mock.calls == 1 resp = requests.get(url) assert resp.status_code == status assert resp.json() == response_json assert mock.calls == 2